...
Hi,
you are right about the synchronization problem within a service file exec
environment, at least as you showed it in that particular Bugzilla case.
Let's review it once again here (I am on F15), but I reserve the right to be
wrong as I have mostly ignored systemd for the time being :-)
Your nfslock.service file:
[Unit]
Description=NFS file locking service.
After=syslog.target network.target rpcbind.service
ConditionPathIsDirectory=/sys/module/sunrpc
[Service]
Type=forking
PIDFile=/var/run/sm-notify.pid
EnvironmentFile=/etc/sysconfig/nfsservices
ExecStartPre=/sbin/modprobe -q lockd $LOCKDARG
ExecStartPre=/sbin/rm -f /var/run/sm-notify.pid
ExecStart=/sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT
ExecStart=/sbin/sysctl -w fs.nfs.nlm_udpport=$LOCKD_UDPPORT
ExecStart=/sbin/rpc.statd $RPCSTATDARS
ExecStartPost=/sbin/sysctl -w fs.nfs.nlm_tcpport=0
ExecStartPost=/sbin/sysctl -w fs.nfs.nlm_udpport=0
[Install]
WantedBy=multi-user.target
Also=rpcbind.socket
or a variation of the above:
...
ExecStartPre=/sbin/modprobe -q lockd $LOCKDARG
...
ExecStartPre=/sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT
...
and the failure is:
$ systemctl status nfslock.service
nfslock.service - NFS file locking service.
Loaded: loaded (/lib/systemd/system/nfslock.service)
Active: failed since Thu, 07 Jul 2011 14:35:39 -0400; 28s ago
Process: 2186 ExecStartPre=/sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT
(code=exited, status=255)
Process: 2184 ExecStartPre=/sbin/modprobe -q lockd $LOCKDARG (code=exited,
status=0/SUCCESS)
$
Yes, there is a potential problem as jobs can be created for execution in one
order, but actually scheduled for execution or executed in a different order.
So, what are the solutions ?
- in this particular case
There is a service file for that purpose already ?
$ cat /lib/systemd/system/systemd-modules-load.service
...
[Unit]
Description=Load Kernel Modules
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service
Before=sysinit.target shutdown.target
ConditionDirectoryNotEmpty=/etc/modules-load.d
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-modules-load
$
and this service file too ?
$ cat /lib/systemd/system/systemd-sysctl.service
...
[Unit]
Description=Apply Kernel Variables
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service
Before=sysinit.target shutdown.target
ConditionPathExists=|/etc/sysctl.conf
ConditionDirectoryNotEmpty=|/etc/sysctl.d
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-sysctl
$
The sys admin would:
- add a required lockd.conf to /etc/modules-load.d/
- edit /etc/sysctl with required param settings
I guess you could modify the nfslock.service file like this:
...
Requires=systemd-modules-load.service systemd-sysctl.service
...
After=syslog.target network.target rpcbind.service ystemd-modules-load.service
systemd-sysctl.service
...
and without these:
...
ExecStartPre=/sbin/modprobe -q lockd $LOCKDARG
ExecStart=/sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT
ExecStart=/sbin/sysctl -w fs.nfs.nlm_udpport=$LOCKD_UDPPORT
...
I hope that the env variables used by modprobe and 'sysctl -w' as used here
($LOCKDARG, $LOCKD_TCPPORT, $LOCKD_UDPPORT) would be available in the above
corresponding service execution envs as being "required" "sub-services"
(see Requires=... and After=...) to nfslock.service, which provides for
EnvironmentFile=/etc/sysconfig/nfsservices .
I hope that would work as desired, that is, synchronously.
- systemd has to manipulate SYSTEMD.EXEC(5) scheduling environment to make
sure that sequential execution as in a service file *means* synchronous
execution, with internal completion code checking and error processing.
Warning:
manipulating scheduling environment is always tricky and can cause
problems and complications, in particular in real-time environment, as
multithreading programming shows.
- perhaps systemd needs some conditional constructs to check for completion
code of commands executed (sequentially) in a service file.
e.g.
ExecStartPre="/sbin/modprobe -q lockd $LOCKDARG",SetOnError=error1
ExecStartPre="/sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT",IfError=error1=0
This would be useful here, but it appears to duplicate options from
systemd.unit(5) and systemd.service(5).
Well, systemd was supposed to simplify those silly and primitive bash-based
SysV and LSB system init environments, cure the lack of parallelism, etc ...
Sorry, just having a bad hair day :-)
JB
Maria Callas - Bellini - Il Pirata - Part 2 (Final Scene)