Discussion:
time-sync.target
Add Reply
Pietro Paolini
2017-05-30 15:57:00 UTC
Reply
Permalink
Raw Message
Hi everybody,

I am trying to configure my systemd to run my service *after* the timesyncd
service is synchronized with the NTP server, unfortunately adding the
"After=time-sycd.target" does not work as I can't see any change in the
behavior - my service is started immediately anyway.

Reading here https://github.com/systemd/systemd/issues/5097 it looks like
there is a problem with that target but I am not sure where to start from,
is it feasible to patch the systemd-timesyncd daemon to correct the
behavior ?

I am not very much familiar with the systemd internals or API but I could
learn the bits I need.

As alternative I could write my wrapper around the daemon as done in the
link reporting the issue, both ways I will need to read something
enlightening on the matter, would you be able to point me into the right
direction ?

Thanks,
P.
--
Notice: This email is confidential and may contain copyright material of
members of the Ocado Group. Opinions and views expressed in this message
may not necessarily reflect the opinions and views of the members of the
Ocado Group.



If you are not the intended recipient, please notify us immediately and
delete all copies of this message. Please note that it is your
responsibility to scan this message for viruses.



Fetch and Sizzle are trading names of Speciality Stores Limited and Fabled
is a trading name of Marie Claire Beauty Limited, both members of the Ocado
Group.



References to the “Ocado Group” are to Ocado Group plc (registered in
England and Wales with number 7098618) and its subsidiary undertakings (as
that expression is defined in the Companies Act 2006) from time to time.
The registered office of Ocado Group plc is Buildings One & Two, Trident
Place, Mosquito Way, Hatfield, Hertfordshire, AL10 9UL.
Luke Shumaker
2017-05-31 01:36:52 UTC
Reply
Permalink
Raw Message
On Tue, 30 May 2017 11:57:00 -0400,
Post by Pietro Paolini
Hi everybody,
I am trying to configure my systemd to run my service *after* the
timesyncd service is synchronized with the NTP server, unfortunately
adding the "After=time-sycd.target" does not work as I can't see any
change in the behavior - my service is started immediately anyway.
Reading here https://github.com/systemd/systemd/issues/5097 it looks
like there is a problem with that target but I am not sure where to
start from, is it feasible to patch the systemd-timesyncd daemon to
correct the behavior ?
Yes, this is a problem with timesyncd, and it should eventually be
patched.

The problem with patching it is that without re-thinking something, it
is impossible to have it block time-sync.target without also risking
systemd-timesyncd.service from timing out.

The only solution that I can think of is to have a second helper
process that can't time out that waits for a signal from timesyncd;
and have that process block time-sync.target. But, the systemd team
hasn't yet decided if this solution is acceptable to them.

So, anyway, I went ahead wrote such a helper program, and a wrapper
for timesyncd that handles sending the signal.
Post by Pietro Paolini
As alternative I could write my wrapper around the daemon as done in
the link reporting the issue, both ways I will need to read
something enlightening on the matter, would you be able to point me
into the right direction ?
You should be able to install and use the wrapper that I wrote.
There's nothing specific to my use-case about it. If you install it,
then the "time-sync.target" should "just work" correctly with
timesyncd.

Of course, in the long-term it would be preferable to patch timesyncd,
instead of having to install separate wrapper to fix the behavior.
But for today, it works.
--
Happy hacking,
~ Luke Shumaker
Pietro Paolini
2017-05-31 08:33:09 UTC
Reply
Permalink
Raw Message
Post by Luke Shumaker
On Tue, 30 May 2017 11:57:00 -0400,
Post by Pietro Paolini
Hi everybody,
I am trying to configure my systemd to run my service *after* the
timesyncd service is synchronized with the NTP server, unfortunately
adding the "After=time-sycd.target" does not work as I can't see any
change in the behavior - my service is started immediately anyway.
Reading here https://github.com/systemd/systemd/issues/5097 it looks
like there is a problem with that target but I am not sure where to
start from, is it feasible to patch the systemd-timesyncd daemon to
correct the behavior ?
Yes, this is a problem with timesyncd, and it should eventually be
patched.
The problem with patching it is that without re-thinking something, it
is impossible to have it block time-sync.target without also risking
systemd-timesyncd.service from timing out.
The only solution that I can think of is to have a second helper
process that can't time out that waits for a signal from timesyncd;
and have that process block time-sync.target. But, the systemd team
hasn't yet decided if this solution is acceptable to them.
So, anyway, I went ahead wrote such a helper program, and a wrapper
for timesyncd that handles sending the signal.
Post by Pietro Paolini
As alternative I could write my wrapper around the daemon as done in
the link reporting the issue, both ways I will need to read
something enlightening on the matter, would you be able to point me
into the right direction ?
You should be able to install and use the wrapper that I wrote.
There's nothing specific to my use-case about it. If you install it,
then the "time-sync.target" should "just work" correctly with
timesyncd.
Of course, in the long-term it would be preferable to patch timesyncd,
instead of having to install separate wrapper to fix the behavior.
But for today, it works.
Thanks! Unfortunately it is not an option to install the Go runtime system
on the board I am working with, is there a place where I can find docs
about writing my own wrapper in C ?
Cheers,
Pietro
Post by Luke Shumaker
--
Happy hacking,
~ Luke Shumaker
--
Notice: This email is confidential and may contain copyright material of
members of the Ocado Group. Opinions and views expressed in this message
may not necessarily reflect the opinions and views of the members of the
Ocado Group.



If you are not the intended recipient, please notify us immediately and
delete all copies of this message. Please note that it is your
responsibility to scan this message for viruses.



Fetch and Sizzle are trading names of Speciality Stores Limited and Fabled
is a trading name of Marie Claire Beauty Limited, both members of the Ocado
Group.



References to the “Ocado Group” are to Ocado Group plc (registered in
England and Wales with number 7098618) and its subsidiary undertakings (as
that expression is defined in the Companies Act 2006) from time to time.
The registered office of Ocado Group plc is Buildings One & Two, Trident
Place, Mosquito Way, Hatfield, Hertfordshire, AL10 9UL.
Luke Shumaker
2017-05-31 18:22:28 UTC
Reply
Permalink
Raw Message
On Wed, 31 May 2017 04:33:09 -0400,
Post by Luke Shumaker
Thanks! Unfortunately it is not an option to install the Go runtime
system on the board I am working with, is there a place where I can
find docs about writing my own wrapper in C ?
Go is a compiled language, there is no separate runtime to install.
It's also easy to cross-compile Go programs. However, Go binaries
tend to have a minimum size of about 1.5MB, so I can appreciate not
wanting to add another ~4MB for two tiny programs.

Each of the programs is pretty simple. If you know C, the Go should
be pretty simple to read; I think the weirdest bit to a C programmer
is that "go fn()" runs "fn()" in a separate thread.

The systemd-timesyncd-wait program is super-simple. It recieves a
socket from systemd, waits for some data to come in on it, then exits.
Most of the Go version is re-implementing libsystemd's
sd_listen_fds(). Without actually testing it, I think a C
implementation is as simple as:

#include <errno.h>
#include <error.h>
#include <unistd.h>

#include <systemd/sd-daemon.h>

int main() {
int r;
char dat[4096];

r = sd_listen_fds(0);
if (r != 1)
error(1, 0, "expected 1 fd, got %d\n", r);

for (;;) {
r = read(SD_LISTEN_FDS_START, dat, sizeof(dat));
if (r < 0)
error(127, errno, "read");
if (r > 0)
return 0;
}
}

The systemd-timesyncd-wrap program is a bit more complicated. It
looks the socket used by sd_notify(), and intercepts it. So look at
the socket pointed to by $NOTIFY_SOCKET, create an identical socket,
and then run the real systemd-timesyncd with $NOTIFY_SOCKET set to the
copy (also, you should set $WATCHDOG_PID to the PID of the real
systemd-timesyncd, but that turned out to be tricky in Go, and wasn't
too important, so I just unset it). We listen on the copy, and simply
forward all messages to the original socket; with the exception that
if the message has a line that starts with "STATUS=Synchronized", then
we *also* send a message to systemd-timesyncd-wait via
"/run/timesyncd/time-sync.sock". The tricky part is that messages
sent on $NOTIFY_SOCKET may have out-of-band control message (cmsg)
data associated with them, and we have to forward this too. Control
messages are poorly documented in both C and Go. To receive them,
look manager.c:manager_dispatch_notify_fd(), and to send them, look at
libsystemd's sd_pid_notify_with_fds().

If you're writing C anyway, it may be easier to patch
systemd-timesyncd to send the additional message when it sends the
"STATUS=Syncronized..." message, rather than wrapping it.
--
Happy hacking,
~ Luke Shumaker
Loading...