infinite loop in dbcancel

Joshua Lang <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <CAFTwDJT4CTMCsk2vVyiHKS8+RLdsSu9_p6SBNA8v3KSFzpty7A@mail.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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.