[freetds] infinite loop in dbcancel

Joshua Lang joshua.h.lang at gmail.com
Sun Mar 20 12:06:43 EDT 2016


Excellent. Thanks for the quick turnaround!

> On Mar 20, 2016, at 4:22 AM, Frediano Ziglio <freddy77 at gmail.com> wrote:
> 
> Fixed (master and 0.95)!
> 
> Expect usually snapshots tomorrow.
> 
> Frediano
> 
> 
> 2016-03-17 21:28 GMT+00:00 Joshua Lang <joshua.h.lang at gmail.com>:
>> Ugh. Well I don't have a Windows host setup currently for testing...
>> Also, it does seem strange that the code loops if the returned error is
>> EWOULDBLOCK or EAGAIN. That should never happen in a read after the select
>> (poll) has successfully returned the file descriptor is ready for reading.
>> 
>>> On Thu, Mar 17, 2016 at 2:24 PM, Frediano Ziglio <freddy77 at gmail.com> wrote:
>>> 
>>>> On 17 Mar 2016 21:21, "Joshua Lang" <joshua.h.lang at gmail.com> wrote:
>>>> 
>>>> That seems reasonable. Would you like a pull request?
>>> 
>>> You can. However I think on Windows you have to call a function to set the
>>> error and I don't know which constant would be better. On Windows these
>>> kind of error (socket ones) have no relation with c errno
>>> 
>>> Frediano
>>> 
>>>> On Thu, Mar 17, 2016 at 12:55 PM, Frediano Ziglio <freddy77 at gmail.com>
>>>> wrote:
>>>> 
>>>>> 2016-03-16 19:23 GMT+00:00 Joshua Lang <joshua.h.lang at gmail.com>:
>>>>>> FreeTDS version: 0.95.79
>>>>>> OS: Debian 7.9 (wheezy)
>>>>>> 
>>>>>> Here's the scenario:
>>>>>> 
>>>>>> Application has a long-running (pooled) connection to a database.
>>>>>> The database is restarted.
>>>>>> The application then consumes as much of one CPU as it can.
>>>>>> 
>>>>>> Unfortunately I have yet to find a simple repro for this issue
>>> locally,
>>>>> but
>>>>>> here is what I've found debugging the live application:
>>>>>> 
>>>>>> strace shows a constant stream of the following call:
>>>>>> 
>>>>>> poll([{fd=150, events=POLLOUT}, {fd=98, events=POLLIN}], 2, 1000) = 1
>>>>>> ([{fd=150, revents=POLLOUT|POLLERR|POLLHUP}])
>>>>>> 
>>>>>> The (relevant) stack trace from gdb:
>>>>>> 
>>>>>> (gdb) bt
>>>>>> #0  0x00007f1fae4d16b3 in *__GI___poll (fds=<optimized out>,
>>>>>> nfds=<optimized out>, timeout=1000)
>>>>>>    at ../sysdeps/unix/sysv/linux/poll.c:87
>>>>>> #1  0x00007f1fa50ff883 in tds_select () from
>>>>>> /opt/zillow/services/mortgage-api-external/zpr/lib/libsybdb.so.5
>>>>>> #2  0x00007f1fa50ffe70 in tds_goodwrite () from
>>>>>> /opt/zillow/services/mortgage-api-external/zpr/lib/libsybdb.so.5
>>>>>> #3  0x00007f1fa5100062 in tds_connection_write () from
>>>>>> /opt/zillow/services/mortgage-api-external/zpr/lib/libsybdb.so.5
>>>>>> #4  0x00007f1fa51046f7 in tds_put_cancel () from
>>>>>> /opt/zillow/services/mortgage-api-external/zpr/lib/libsybdb.so.5
>>>>>> #5  0x00007f1fa50f574b in tds_send_cancel () from
>>>>>> /opt/zillow/services/mortgage-api-external/zpr/lib/libsybdb.so.5
>>>>>> #6  0x00007f1fa50c3560 in dbcancel () from
>>>>>> /opt/zillow/services/mortgage-api-external/zpr/lib/libsybdb.so.5
>>>>>> 
>>>>>> 
>>>>>> I've stepped through this with gdb and here are the results:
>>>>>> 1. tds_select is called, returning -1 (verified in gdb)
>>>>>> 2. errno returns to 11 (EAGAIN) (verified in gdb, by stepping through
>>> the
>>>>>> c-lib function call to return it)
>>>>>> 3. TDSSOCK_WOULDBLOCK therefore causes the loop to repeat:
>>>>>> https://github.com/FreeTDS/freetds/blob/master/src/tds/net.c#L803
>>> and
>>>>> we're
>>>>>> back to step 1 and an infinite loop
>>>>>> 
>>>>>> The TDSSOCK_WOULDBLOCK seems strange to me, and the comment after it
>>>>>> agrees. I wouldn't expect the socket read to block if the poll call
>>> just
>>>>>> indicated it was ready for read.
>>>>> 
>>>>> 
>>>>> I think the problem is in tds_select. After poll returns 1 we check
>>>>> for error and return correctly -1 as failure however errno is not set
>>>>> so it's still the old value. I would try to set to something like
>>>>> EPIPE before returning -1.
>>>>> 
>>>>> Frediano
>>>>> _______________________________________________
>>>>> FreeTDS mailing list
>>>>> FreeTDS at lists.ibiblio.org
>>>>> http://lists.ibiblio.org/mailman/listinfo/freetds
>>>> _______________________________________________
>>>> FreeTDS mailing list
>>>> FreeTDS at lists.ibiblio.org
>>>> http://lists.ibiblio.org/mailman/listinfo/freetds
>>> _______________________________________________
>>> FreeTDS mailing list
>>> FreeTDS at lists.ibiblio.org
>>> http://lists.ibiblio.org/mailman/listinfo/freetds
>> _______________________________________________
>> FreeTDS mailing list
>> FreeTDS at lists.ibiblio.org
>> http://lists.ibiblio.org/mailman/listinfo/freetds
> _______________________________________________
> FreeTDS mailing list
> FreeTDS at lists.ibiblio.org
> http://lists.ibiblio.org/mailman/listinfo/freetds


More information about the FreeTDS mailing list