[systemd-devel] Perl Net::DBus, org.freedesktop.system1 and inhibitor locks

Michael Hirmke mh at mike.franken.de
Wed May 25 10:17:00 UTC 2016


Hi *,

I'd like to write a script, which can listen to the PepareForSleep
signal from systemd-logind. When it catches the signal, it should do a
few things in the context of the user. While doing this, it should
inhibit the sleep process. It gets started as autostart script in KDE.
For this purpose I use perl and the module Net::DBus.
Actually I am able to connect to the bus, attach to the appropriate
signal and run something, when getting the signal.

But:

- I only can take delay locks. Whenever I try to take a *blocking* lock,
  nothing happens, as if it is completely ignored. I don't get any
  error message, though.
  When using *delay* locks and the maximum inhibition time has been
  exceeded, I get

  "systemd-logind: Delay lock is active (UID <uid>/<user>, PID
  <pid>/dbus_logind) but inhibitor timeout is reached."

  So it seems to work in this case, but why not with blocking locks?

- I am not able to close the file descriptor in the pre block of the
  signal handler. Whenever I try, I get an error, that the descriptor
  is closed.
  When I try to take the lock again in the post block of the signal
  handler, I get a second entry in the inhibitor list with the same
  contents. After a few sleep/resume cycles the entries get more and
  more.

Does anyone have any hint, what I might do wrong in my script or where
my understanding is wrong?

This is the script in question:

------------------------< snip snip snip >-----------------------------
#!/usr/bin/perl -w

use 5.005;
use strict;
use Getopt::Std;
use IO::Handle;
use Log::Journald;
use Net::DBus;
use Net::DBus::Reactor;
use POSIX qw( _exit );
use Scalar::Util qw( openhandle );
use Sys::Syslog qw( :macros );

$SIG{INT} = \&dbus_logind_SignalHandler;

STDOUT->autoflush( 1 );
STDERR->autoflush( 1 );

my $FD = -1;
my $oif = getInterface();
$oif->connect_to_signal( "PrepareForSleep", \&onPrepareForSleep ) || die $!;
takeLock( $oif );
my( $reactor ) = Net::DBus::Reactor->main();
$reactor->run();
exit( 0 );

sub getInterface {
  my $bus = Net::DBus->system || die $!;
  my $osvc = $bus->get_service( "org.freedesktop.login1" ) || die $!;
  my $oif = $osvc->get_object(
              "/org/freedesktop/login1",
              "org.freedesktop.login1.Manager"
            ) || die $!;
  return( $oif );
}

sub takeLock {
  my( $oif ) = @_;
  $FD = $oif->Inhibit( 'sleep', 'dbus_sleep', 'preparing', 'delay' );
}

sub dropLock {
  if( defined( $FD ) && $FD >= 0 && openhandle( $FD ) ) {
    if( close( $FD ) ) {
      $FD= -1;
    }
  }
}

sub onPrepareForSleep {
  my( $prepost ) = @_;
  if( $prepost ) {
    print "dbus_sleep: in pre\n";
    journal_log( LOG_INFO, "dbus_sleep: in pre" );
    sleep( 20 );
    dropLock();
  } else {
    print "dbus_sleep: in post\n";
    journal_log( LOG_INFO, "dbus_sleep: in post" );
    takeLock( getInterface() );
  }
  return( 0 );
}

sub dbus_logind_SignalHandler {
  my( $_sig ) = shift;
  if( $_sig eq "INT" ) {
    POSIX::_exit( 0 );
  }
}
------------------------< snip snip snip >-----------------------------

Thx 


More information about the systemd-devel mailing list