[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