I'm trying to write own daemon a la very simple MPD (it's operating systems laboratory work). I made it work: it starts like a daemon (output of ps):
1 14877 14877 14877 ? -1 Ss 0 0:00 lab1_daemon
it plays, it gets signals.
The problem is that I can't run it with systemd. I wrote very simple .service file:
[Unit]
Description=Operating systems lab 1 daemon
[Service]
Type=forking
PIDFile=/run/lab1_daemon.pid
ExecStart=/path/lab1_daemon
[Install]
WantedBy=multi-user.target
But when I run daemon with systemctl start it hangs for 0.5 min and then in logs I see:
Failed to read PID from file /run/lab1_daemon.pid: Invalid argument
lab1_daemon.service never wrote its PID file. Failing.
But it did! I checked it:
-rw-r--r-- 1 root root 13 Mar 5 00:13 /run/lab1_daemon.pid
What have I done wrong?
PS: I even tried daemon function to check, that I did daemonizing correctly. But I got same results. Minimal source code (58 LOC, moved from pastebin):
#define _BSD_SOURCE
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 199506L
#define _D_XOPEN_SOURCE 700
#define NAME "lab1_daemon"
#define PID_FILE_NAME "/run/" NAME ".pid"
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int lockfile(int fd)
{
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
return fcntl(fd, F_SETLK, &fl);
}
bool is_already_running(char const *lock_file_name)
{
int lock_file = open(lock_file_name, O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (lock_file < 0)
exit(1);
if (lockfile(lock_file) < 0) {
if (errno == EACCES || errno == EAGAIN) {
close(lock_file);
return true;
}
exit(1);
}
ftruncate(lock_file, 0);
char buf[16];
sprintf(buf, "PPID: %ld\n", (long)getpid());
write(lock_file, buf, strlen(buf) + 1);
return false;
}
int main(void)
{
if (is_already_running(PID_FILE_NAME))
exit(EXIT_FAILURE);
daemon(0, 0);
sleep(10);
exit(EXIT_SUCCESS);
}