gemoroy has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks!

I am new to threads, so i faced such a problem:

I had written a class, witch works with dbm, but, when i am trying to call a sub, wich accesses db handle,

i'm getting such an error:Thread 1 terminated abnormally: DBD::DBM::db prepare failed: handle 2 is owned by thread 80100a000 not current thread 801051000 (handles can't be shared between threads and your driver may need a CLONE method added) at test_mod.pm line 55 line 55 is: $sql = $dbh->prepare($query) || die($dbh->errstr);

Please could you explain why it is owned by other thread, when i am calling it from with only thread i have created, and what is CLONE method?

Or a different class method by default executed by it's own thread or smth like that?

Thanks a lot in advance!

Replies are listed 'Best First'.
Re: Threads and handle sharing
by BrowserUk (Patriarch) on Jun 27, 2009 at 02:47 UTC
    could you explain why it is owned by other thread, when i am calling it from with only thread i have created,

    You have only created one thread, but every process starts with one thread, so now you have two.

    My guess is--if you posted the code, we wouldn't have to guess--that you have something like this:

    use threads; use DBI; my $dbh = DBI->connect('dbi:DBM:'); ... my $thread = threads->create( \&thread ); ... sub thread { ... $sql = $dbh->prepare($query) || die($dbh->errstr); #55 ... }
    1. When your process starts, it starts with one thread.
    2. Within that thread you create a DB handle;
    3. You then create a(nother) thread that attempts to use that handle.

    When the new thread is created, Perl clones (creates a copy of) the perl scalar that contains the DB handle for use by that new thread, but as the DBD driver you're using doesn't have a CLONE method, only the handle is cloned, not the object that lives behind it.

    So, when you attempt to use the cloned handle within the new thread, DBI is detecting that it was created for a different thread and is telling you--very clearly--that that isn't going to work.

    One workaround would be to move the creation of the handle--ie. the DBI->connect(...) into the thread also. But be aware that it will mean not using DBI from your main thread. And if your thread is short lived and created repeatedly, then it will cost you the process of reconnected each time, which may or may not be a problem.

    Please note the "My guess is" up front and take this speculation in knowledge of it. If you posted the code, you'd be more likely to get a definitive answer.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.