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

Hi monks,

I am trying to use Net::DBus in a threaded script, and I have a hard time doing this. I have not found anything about the threadsafeness of Net::DBus, it might just not be possible to do what I want.

If I create my Net::DBus::RemoteObject outside of the threads it will be used on, I have errors. I thus tried to create one object per thread, and I have the same behaviour. Here is a small example script and its output.

#!/usr/bin/perl use strict; use warnings; use threads; my $th1 = threads->create(\&run, 1); my $th2 = threads->create(\&run, 2); sleep; exit; sub run { my $num = shift; my ($bus, $service, $purple); eval {$bus = Net::DBus->session}; if ($@) {print "th$num: Error in bus: $@\n"; threads->exit()} eval {$service = $bus->get_service('im.pidgin.purple.PurpleService') }; if ($@) {print "th$num: Error in service: $@\n"; threads->exit()} eval {$purple = $service->get_object('/im/pidgin/purple/PurpleObject', 'im.pidgin.purple.PurpleInterface')}; if ($@) {print "th$num: Error in purple: $@\n"; threads->exit()} eval {$purple->connect_to_signal ('ReceivedImMsg', \&read_cb)}; if ($@) {print "th$num: Error in connect: $@\n"; threads->exit()} eval {Net::DBus::Reactor->main()->run()}; if ($@) {print "th$num: Error in run: $@\n"; threads->exit()} } sub read_cb { print scalar(@_) , ' params', "\n"; }

So get bus, get service, get object, set callback and run. This works very well single threaded. Here is the output of this particular script:

th1: Error in service: Can't call method "get_interval" without a pack +age or object reference at /usr/lib/perl5/Net/DBus/Reactor.pm line 21 +1. Thread 1 terminated abnormally: Can't call method "get_interval" witho +ut a package or object reference at /usr/lib/perl5/Net/DBus/Reactor.p +m line 211. th2: Error in service: org.freedesktop.DBus.Error.NoMemory: Not enough + memory Thread 2 terminated abnormally: main=HASH(0x9ffd850) at /usr/lib/perl5 +/threads.pm line 101.

Trying to add a lock makes it better up to the run(), which will fail with the same kind of error if it is not inside the lock (which would defeat the purpose).

Would somebody know what is wrong with this code? Following the advice of http://perldoc.perl.org/threads.html#WARNINGS, instead of use'ing the DBus modules I tried to require them inside the thread, with no effect.

If it helps, the background is the following:

Thanks for any advice or pointer on this.

Replies are listed 'Best First'.
Re: Net::DBus and threads
by lom (Sexton) on Jul 05, 2009 at 09:22 UTC

    Self answer:

    The bus ($bus = Net::DBus->session()) actually re-uses an internal shared bus connection in libdbus.so. This does not fit well in Perl's threads, but there is the possibility to ask for a private bus by passing the option private => 1.

    That way, as long as the objects are not shared (I have not tried that) it is possible to have one working bus connection per thread.