[systemd-devel] time-sync.target
Luke Shumaker
lukeshu at lukeshu.com
Wed May 31 18:22:28 UTC 2017
On Wed, 31 May 2017 04:33:09 -0400,
Pietro Paolini wrote:
> 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
More information about the systemd-devel
mailing list