freetds AT lists.ibiblio.org
Subject: FreeTDS Development Group
List archive
- From: "James K. Lowden" <jklowden AT freetds.org>
- To: freetds AT lists.ibiblio.org
- Subject: Re: [freetds] tinytds based on freetds crashing
- Date: Wed, 4 Apr 2012 17:18:13 -0400
On Wed, 4 Apr 2012 13:00:05 +0200
Krzysztof Chodak <krzysztof.chodak AT gmail.com> wrote:
> > Here it is: TDSDUMP log with a (ruby/tinytds/freetds) crash at the
> > end
>
> list does not like zip attachments so file is placed here:
> https://docs.google.com/open?id=0B8Pbr6Jr1eaCZnFCUDk3LWxTYXVncFpCaUdfdjhIdw
(What message did you get posting a zip file? It should be
permitted provided it's under 75 KB.)
The TDSDUMP log clarifies several points.
FreeTDS 0.91
TDS 7.1
Windows (log file is on C: drive)
client charset is UTF-8 (unusual but OK)
The trouble starts when the server disconnects unexpectedly. It ends
when unbounded recursion caused by the application's error handler
consumes the stack and crashes the process.
Why the server disconnected isn't clear or even certain. All that we
know is that the last write returned "Connection reset by peer", which
normally indicates the connection was closed by the remote.
The last packet sent is on line 81590 of the log file
SELECT TOP (1) [users].* FROM [users]
WHERE [users].[login] = N''bradoscb''
Immediately beneath the dumped packet we see
net.c:667:send(2) failed: 10054
(WSAECONNRESET: Connection reset by peer.)
which tells us the library detected the OS error. Then
util.c:331:tdserror(03a04588, 03fe49b0, 20006, 10054)
dblib.c:7929:dbperror(03d32008, 20006, 10054)
dblib.c:7981:20006: "Write to the server failed"
per normal, then
dblib.c:5780:dbgetuserdata(03d32008)
dblib.c:5780:dbgetuserdata(03d32008)
dblib.c:4880:dbdead(03d32008) [alive]
wrong. A disconnected session is anything but alive.
dblib.c:4639:dbsqlok(03d32008)
dblib.c:4669:dbsqlok() not done, calling tds_process_tokens()
db-lib still thinks the session is up ...
token.c:540:tds_process_tokens(03fe49b0, 00226220, 0022621c, 0x6914)
util.c:156:Changed query state from PENDING to READING
util.c:331:tdserror(03a04588, 03fe49b0, 20004, 10054)
dblib.c:7929:dbperror(03d32008, 20004, 10054)
dblib.c:7981:20004: "Read from the server failed"
but the read failed ...
dblib.c:5780:dbgetuserdata(03d32008)
dblib.c:5780:dbgetuserdata(03d32008)
dblib.c:4880:dbdead(03d32008) [alive]
dblib.c:4639:dbsqlok(03d32008)
dblib.c:4669:dbsqlok() not done, calling tds_process_tokens()
and we enter an infinite loop.
Analysis
---------
Windows returns a valid error code WSAECONNRESET. This is reported to
the log in tds/net.c:tds_goodwrite() on line 667. That logic closes
the socket and returns -1 to tds_write_packet().
How did we get there? The log shows
dblib.c:6862:dbsqlsend(03d32008)
write.c:168:tds_put_string wrote 194 bytes
tds_put_string() calls
tds_put_n() calls
tds_write_packet
tds_write_packet() returrns TDS_FAIL to tds_put_n()
which discards the return code. :-(
Propogating the error code is not the only way error information is
provided to db-lib from libtds. tds_goodwrite() also calls tdserror
(), which calls the client's error handler. We see that in the log, too
util.c:331:tdserror(03a04588, 03fe49b0, 20006, 10054)
dblib.c:7929:dbperror(03d32008, 20006, 10054)
dblib.c:7981:20006: "Write to the server failed"
What we do *not* see in the log is the product of the next line in
tdserror()
tdsdump_log(TDS_DBG_FUNC,
"tdserror: client library returned %s(%d)\n", retname(rc), rc);
The missing message in the log indicates the error handler is Charlie on
the MTA: it Never Returned.
It would appear -- whether by design or not -- that the
client-installed error handler makes db-lib calls, in particular
dbsqlok(). Don't do that. It engenders infinite recursion just
as evinced by the log:
dblib.c:4669:dbsqlok() not done, calling tds_process_tokens()
token.c:540:tds_process_tokens(03fe49b0, 00226220, 0022621c, 0x6914)
util.c:331:tdserror(03a04588, 03fe49b0, 20004, 10054)
dblib.c:7929:dbperror(03d32008, 20004, 10054)
dblib.c:7981:20004: "Read from the server failed"
# no tdserror message here
# to indicate the handler's return code
...
dblib.c:4639:dbsqlok(03d32008) # from within handler
dblib.c:4669:dbsqlok() not done, calling tds_process_tokens()
(It looks like an infinite loop, but it's infinite recursion.
Computationally equivalent constructs, just one is more familar to C
programmers than the other.)
Incidentally, this would also explain why dbdead() reports "[active]".
In tds_goodread(), the socket isn't closed until after tdserror()
returns. Because the socket is still open within the recursion, all
calls to dbdead() continue to find the socket open and it reports
"active".
Give your error handler a nickle and let it return. Otherwise it will
eventually devour the stack along with your process.
--jkl
-
Re: [freetds] tinytds based on freetds crashing,
Krzysztof Chodak, 04/02/2012
-
Re: [freetds] tinytds based on freetds crashing,
James K. Lowden, 04/02/2012
-
Message not available
-
Re: [freetds] tinytds based on freetds crashing,
Krzysztof Chodak, 04/04/2012
-
Re: [freetds] tinytds based on freetds crashing,
James K. Lowden, 04/04/2012
- Re: [freetds] tinytds based on freetds crashing, Ken Collins, 04/04/2012
-
Re: [freetds] tinytds based on freetds crashing,
Frediano Ziglio, 04/05/2012
-
Re: [freetds] tinytds based on freetds crashing,
Krzysztof Chodak, 04/05/2012
- Re: [freetds] tinytds based on freetds crashing, Frediano Ziglio, 04/05/2012
- Re: [freetds] tinytds based on freetds crashing, Krzysztof Chodak, 04/05/2012
- Re: [freetds] tinytds based on freetds crashing, Frediano Ziglio, 04/05/2012
- Re: [freetds] tinytds based on freetds crashing, Ken Collins, 04/05/2012
- Re: [freetds] tinytds based on freetds crashing, James K. Lowden, 04/05/2012
- Re: [freetds] tinytds based on freetds crashing, Krzysztof Chodak, 04/05/2012
-
Re: [freetds] tinytds based on freetds crashing,
Krzysztof Chodak, 04/05/2012
-
Re: [freetds] tinytds based on freetds crashing,
James K. Lowden, 04/04/2012
- Re: [freetds] tinytds based on freetds crashing, James K. Lowden, 04/05/2012
-
Re: [freetds] tinytds based on freetds crashing,
Krzysztof Chodak, 04/04/2012
-
Message not available
-
Re: [freetds] tinytds based on freetds crashing,
James K. Lowden, 04/02/2012
Archive powered by MHonArc 2.6.24.