(I've added dbi-dev as this seems relevant)

Tim Bunce wrote:
On Sat, Sep 16, 2006 at 08:31:54PM -0400, Sam Tregar wrote:
On Sat, 16 Sep 2006, Dean Arnold wrote:

I think your best bet might be to work with the DBD::mysql maintainers
to implement some driver-specific nonblocking versions of
execute/prepare (and maybe fetch), as well as support for
'out of band' cancel.
That's an interesting idea.

For any driver that uses a network socket to connect you could close()
the socket in the signal handler to (relatively) safely timeout.

Should be fairly clean/safe for the db client library state, though
unsafe signals means there's still a chance perl's internal state could
be corrupted.

On the server-side the query may be left running on databases that
don't detect disconnects (which I think still includes mysql).

A minor problem with this approach is how to determine the socket file
descriptor. For drivers that don't/can't make the socket fd available,
it requires checking which fd's are open before and after the connect.
Kludgy but effective.


Yow...how many client libs surface the socket descriptor ? Not too many
I'm aware of. And the 'sift and kill' approach of finding fd's is likewise
an opportunity for disaster, since you don't know how many fd's may have
been opened in the process of setting up a connection, and some platforms
don't always update fd status as quickly as one might like (I've been down
this particular road to hell for similar purposes). And just dumping the
connection is a pretty severe reaction to something most DBMS's actually
have i/f's to handle gracefully.


Right now I'm putting together
DBIx::Timeout which implements my fork()-based timeout in a reusable
package.  Seems to work, although I've learned to expect forking code
to have unexpected bugs which take time to shake out.

It's mysql specific currently, using $id=$dbh->{thread_id} and do("KILL $id").
(And shouldn't thread_id be mysql_thread_id?)

Would be nice to generalise it. There was talk sometime ago (perhaps on
dbi-dev) of extending the DBI api along these lines:

        $id = $dbh->{SessionId};

        $dbh->kill_session($id);

Would certainly be simple for me to add to the DBI. Then it's just a
simple matter of getting the drivers to implement it :)


Er, but how ? Unless/until the DBI is threadsafe, the only way
for kill_session() to work is by breaking the DBD out of the
current blocking request. Which I assume is to be accomplished
by throwing signals around ?
Keep in mind that the behavior of various DB client libs
wrt signals on any given platform is certainly not standardized;
some blow up, some require extra API calls to handle things, others
just swallow the signal.
(I'll note that signals are conclusive proof that UNIX
was developed in an era when recreational narcotics were readily available
and inexpensive.)

Oh, and then there's the little matter of non-POSIX platforms. Trying to 
reliably
use Perl + fork + signals + some external library on Win32 will certainly
keep a developer busy for a few days.

Once an app (or DBD) is down the rabbit hole of a DBMS client library,
any attempt to standardize such behavior is likely to meet with limited success.

Which brings me back to the notion of non-blocking requests.
Assuming many/most client libs do support an async capability, and a OOB cancel,
then it should be possible to standardize the behavior externally.

Dean Arnold
Presicient Corp.

Reply via email to