Skip to Content.
Sympa Menu

freetds - Re: PHP: losing client/server sync after error (cvs, Sybase ASA)

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: James K. Lowden <jklowden AT speakeasy.org>
  • To: "TDS Development Group" <freetds AT franklin.oit.unc.edu>
  • Cc: lbayuk AT mindspring.com
  • Subject: Re: PHP: losing client/server sync after error (cvs, Sybase ASA)
  • Date: Sun, 1 Sep 2002 19:33:32 -0400


On Sat, 31 Aug 2002 20:21:03 -0400 (EDT), "lbayuk AT mindspring.com"
<lbayuk AT mindspring.com> wrote:

> The trouble seems to start with PHP calling ct_cancel() after an error
> reply. I think something is missing in the protocol here. With
> FreeTDS-0.53, I used to get "Unknown marker 0!!" in Apache's error log
> after each DBMS error reply. But client and server stayed in sync.
> Later revisions to FreeTDS seemed to fix that - no more Unknown marker
> messages, but now I realize it probably wasn't fixed, just masked.
>
> I think it is getting messed up in tds_process_cancel(). I added some
> more tracing, and it thinks it is seeing a 0 byte (the same as FreeTDS
> 0.53), but now it takes that as a Cancel and returns without getting the
> DONE message. But the server isn't done, and still sends a DONE
> message. I think that's what's going on, because the DONE message that
> FreeTDS thinks belongs to the next query actually has the "cancelled"
> flag bit set.
>
> I used a TCP socket tracing program to look more closely (because the
> TDS dump file doesn't show this). I don't understand the reply from the
> server to CANCEL. Here's the client sending CANCEL (type=06):
> 06 01 00 08 00 00 00 00
> Here's the server reply:
> 0f 03 00 08 00 00 00 00
> 04 01 00 11 00 00 00 00 fd 20 00 01 00 00 00 00 00
> The second reply line is a Response (04), Result Set DONE (fd) with
> Cancel bit (20). But what the heck is that first reply line?
> tds_read_packet() is returning 0 when it reads that, because no data
> follows the 8-byte header; then tds_process_cancel() takes that 0 as the
> end of the cancel reply, leaving the real DONE+Cancelled message unread
> until the next query.

Thank you for the problem report, lbayuk.

According to CVS tds_process_cancel() changed, just as you say, in
revision 1.26 of token.c. It was part of the "tight loop" patch. Squish
one bug, find another? OTOH, token.c has seen a lot of work; something
else may be happening.

That "0f" is a "TDS_BUF_NORMAL" response (p. 195 in the document below).
The 0x03 after it is the status byte, indicating TDS_BUFSTAT_EOM (bit 0,
last buffer in a response) and TDS_BUFSTAT_ATTNACK (bit 1,
acknowledgment). That's the expected response to a cancel request.

tds.h doesn't define a token for 0x0f, so I think our cancel protocol
processing isn't interpreting it correctly.

The real question, as far as I can tell, is not what the first response is
(that looks fine according to their doc), but how to know to expect more
incoming data on an "idle" link.

I know almost nothing about the TDS protocol proper, so I'm not going to
be very helpful in telling you what to do. In particular, I don't know
how tds_process_cancel() can know that it's going to receive two (or
more?) responses. According to the documentation, what you say you're
seeing can't happen. I've attached the relevant part from page 20, in
case you don't want to download the whole thing. HTH.

Regards,

--jkl

Sybase's document says:

<doc="http://www.SchemaMania.org/sybase/doc/pdf/tds_50_functional_specifi
cation.pdf">
11. Cancel Protocol

A cancel request is sent using a non-expedited TDS packet with the
header type set to TDS_BUF_URGENT and the packet header status bit
set to TDS_BUFSTAT_ATTN. The client will then read packets from the
server until the cancel is acknowledged with a packet of header type
TDS_BUF_NORMAL and the packet header status bit set to
TDS_BUFSTAT_ATTNACK. The data, if any, in the packet with the
TDS_BUFSTAT_ATTNACK bit set is discard. Once the client receives a
packet with the header status bit TDS_BUFSTAT_ATTNACK set, the dialog
state is returned to an idle state. The client may now issue another
request.

When a TDS_BUFSTAT_ATTN is sent by a client the TDS_BUFSTAT_EOM bit must
also be set in the header status field. The TDS_BUFSTAT_ATTNACK returned
by a server in response to a TDS_BUFSTAT_ATTN must have the
TDS_BUFSTAT_EOM bit set at the end of the response. However, the
TDS_BUFSTAT_ATTNACK can have a data length of 0 or greater. All data in
the TDS_BUFSTAT_ATTNACK response can be safely discard by the client.

Any dialog state information required by the sender of a TDS_BUFSTAT_ATTN
is explictly requested by the sender after the TDS_BUFSTAT_ATTNACK has
been received. The only state information currently required by a client
is the state of all open cursors on the dialog. This state information is
requested by the client by sending a TDS_CURINFO token with a cmd argument
of TDS_CUR_CMD_INQUIRE and a cursor id of 0.

Client Server
-- In-band packet of
type TDS_BUF_URGENT,
status -- Stop current processing,
TDS_BUFSTAT_ATTN | TDS_BUFSTAT_EOM not necessarily on a TDS token
boundary.
-- If packet not TDS_BUFSTAT_EOM,
continue readinguntil
TDS_BUFSTAT_EOM.
<-- Return in-band packet of
type TDS_BUF_NORMAL with
-- Read and discard all packets status of TDS_BUFSTAT_ATTNACK.
between sending of cancel Set TDS_BUFSTAT_EOM bit
and receipt of TDS_BUFSTAT_ATTNACK in last packet.
packet. At this point both
ends are re-synchronized.
-- Server now in idle state.
-- If TDS_BUFSTAT_ATTNACK not also
TDS_BUFSTAT_EOM, continue reading
packetsuntil TDS_BUFSTAT_EOM.

-- Dialog now in idle state.
</doc>




Archive powered by MHonArc 2.6.24.

Top of Page