Skip to Content.
Sympa Menu

freetds - RE: [freetds] goodread... not so fine

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Alex Kiesel <alex.kiesel AT document-root.de>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: RE: [freetds] goodread... not so fine
  • Date: Mon, 19 Jan 2004 12:29:15 +0100

On Mon, 2004-01-19 at 11:47, ZIGLIO, Frediano, VF-IT wrote:

> > > If tds_process_cancel return success state is IDLE so
> > > ct_fetch/ct_results should just return CS_FAIL...
> >
> > I added the check to ct_results/ct_fetch, that improves the situation.
> > However, it doesn't work reliable, though it worked in 80% of
> > my tests.
> >
>
> This means you are able to reproduce it :) Good point. I never used sqsh,
> do you just issue a query that returns a lot of data and then press ctrl-c
> ??

Yes, this is it. You need a lot of data to be able to press Ctrl-C
before the results are all displayed.

Most of the time a 'select * from sysmessages' is enough to have
sufficient time for hitting the keys:)

> > This is a code snipplet from ct_results:
> > /* Check for idle state */
> > if (tds->state == TDS_IDLE)
> > return CS_FAIL;
> >
>
> Perhaps test should be
>
> if (tds->state != TDS_PENDING)
> return CS_FAIL;

Ah, ok. I'll give that a try.

> > It comes down to goodread() which hangs - even I have checked the
> > tds-state before. It seems the ct_cancel can be invoked between the
> > non-idle check and the actual select.
> >
> > Maybe goodread() needs to check the tds-state, too?
> >
>
> No, it's a bad design here. goodread is a low level function and should not
> use state (it's not expected to have knowledge of TDS state). You already
> added code to check TDS_IDLE however or state get set in
> tds_process_result_tokens or state is not TDS_IDLE (nor TDS_DEAD)...
> I don't think sqsh be a multi-thread application... or perhaps it use
> alarm() and issue cancel inside alarm signal ??

Sqsh is not a multithreaded application, but it indeed issues a cancel
within the signal handler. It does two thing from within this handler:
* send a cancel
* set a global variable which gets checked in all normal 'result
processing loops'. Those loops are left when this variable is set to
'1'. One excerpt:

/*
** cmd_do_sigint_cancel():
**
** Cancels current query upon receipt of SIGINT.
*/
static void cmd_do_sigint_cancel( sig, user_data )
int sig ;
void *user_data;
{
if (user_data != NULL)
{
ct_cancel( (CS_CONNECTION*)user_data, (CS_COMMAND*)NULL,
CS_CANCEL_ATTN );
}
sg_canceled = True;
}

And from those loops:
/*
** Suck in the results.
*/
while ((retcode = ct_results( cmd, &result_type ))
== CS_SUCCEED)
{
/*
** Check to see if we were canceled.
*/
if (sg_canceled == True)
{
ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL );
ct_cmd_drop( cmd );
return(CMD_INTERRUPTED);
}

[...]

-Alex




Archive powered by MHonArc 2.6.24.

Top of Page