Recently I needed to find a way to timeout a DBI request. I found the state of the art less than satisfying, involving unsafe signals and a chance of memory corruption deep in Perl's guts:
http://search.cpan.org/user/timb/DBI/DBI.pm#Signal_Handling_and_Canceling_Operations
This led me to create DBIx::Timeout which instead of using unsafe signals:
- Forks a child process which sleeps for $timeout seconds. - Runs your long-running query in the parent process. - If the parent process finishes first it kills the child and returns. - If the child process wakes up it kills the parent's DB thread and exits with a code so the parent knows it was timed out.
Tim Bunce suggested a possible optimization - fork just one child process and have it watch any number of slow queries simultaneously. It would accept assignments via a pipe interface. Seems like a good idea, although it's likely overkill for my usage. The queries I need to timeout are very likely to be long-running, and when they're not don't need to be very fast. The overhead of forking a process that exits almost immediately won't cause any problems, I'm betting.
So, please give it a try! And if you're not a MySQL user, please port it to your DB and send me a patch. It should be an easy job - all you have to do is implement a call to kill another process in the DB (MySQL does it with "KILL $thread_id"). (UPDATE: actually, it's a little more work - you also need to write new tests. The tests I wrote for MySQL use GET_LOCK() to test timeouts - you'll need to do something analgous for your DB.)
-sam
PS: I should note that the mechanism this module uses was suggested by my co-worker Perrin Harkins. I'll add that to the module's POD for the next release.