I've done something similar to what you did...

It went something like this...

- Run query in a separate thread.
- Display dialog box to allow user to abort (instead of having fixed timeout).
- If query finishes first, close dialog box, and query thread is done.
- If user presses abort, cancel the query which then brings control back to the 
thread and the thread is done.

Yes, I ran into race conditions occasionally, but that was fixed by adding 
locks around critical sections of code.  Now, by all appearances, it works like 
a charm.

Now the problem is I did not use Perl and did not use DBI**.  Plus I am not 
familiar with using Threads in Perl and with DBI so I can't tell how well a 
design like this translates to Perl.  I'll leave that for you to evaluate if 
you wish.

** I used the latest language and development platform from a large monopoly 
company that shall remain nameless.

-----Original Message-----
From: Sam Tregar [mailto:[EMAIL PROTECTED]
Sent: Friday, September 15, 2006 3:15 PM
To: dbi-users@perl.org
Subject: Safely timing out DBI queries


Greetings all.  I'm working on an app which allows users to construct
queries using a web UI in a moderately free-form fashion.  There's
plenty of data and hence plenty of rope.  I need to save my users from
themselves by timing-out long-running queries and killing the MySQL
thread.

Our first attempt used alarm() and $SIG{ALRM}.  For reasons described
in the DBI docs, this didn't work - the alarm fires, but only after
the database is done with the query.  I did try the POSIX sigaction()
recipe from the docs, and it worked.  However, I'm very nervous about
the possibility of random instability inherent in unsafe signals.  I'm
hoping to find a better way.

At present I'm imagining something like:

   - Parent forks a child before starting long-running query.

   - Child sleeps for $timeout seconds.

   - If parent finishes first, kills child and proceeds.

   - If child wakes up, kills parent's MySQL thread ID and exits.
     Parent gets "lost connection during query" and assumes that's a
     timeout.

I am concerned about a race condition here.  What happens when the
parent finishes just before the child wakes up?  Seems to me the child
could kill the parent's connection and the parent might not notice.
In my case I think I can get away with this - when the parent finishes
it's about the exit() itself, and doesn't need its DB handle anymore.
I'd like to have a recipe that didn't have this potential problem
though, since I forsee needing this elsewhere in the future.

Ideas?  Am I better off giving in to darkside of POSIX?

-sam

Reply via email to