8

I already read the man page of the pidfile function family. But I don't really understand it. What is the correct usage? Is there a more elaborate example available? I think I understand pidfile_open. But when should I call pidfile_write and prdfile_close? From which process? Parent or child? What parameters do I have to pass to those functions? I propably lack some *nix fundamentals I guess.

Update:

Below you see the example from man pidfile. Why do they fork twice? Why pidfile_close? When I call pidfile_close I can start another daemon. Isn't that unwanted?

 struct pidfh *pfh;
 pid_t otherpid, childpid;

 pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
 if (pfh == NULL) {
         if (errno == EEXIST) {
                 errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
                     (intmax_t)otherpid);
         }
         /* If we cannot create pidfile from other reasons, only warn. */
         warn("Cannot open or create pidfile");
 }

 if (daemon(0, 0) == -1) {
         warn("Cannot daemonize");
         pidfile_remove(pfh);
         exit(EXIT_FAILURE);
 }

 pidfile_write(pfh);

 for (;;) {
         /* Do work. */
         childpid = fork();
         switch (childpid) {
         case -1:
                 syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
                 break;
         case 0:
                 pidfile_close(pfh);
                 /* Do child work. */
                 break;
         default:
                 syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
                 break;
         }
 }

 pidfile_remove(pfh);
 exit(EXIT_SUCCESS);
Jan Deinhard
  • 19,645
  • 24
  • 81
  • 137
  • Does the man page you are seeing have an "example" section? The BSD one does, which illustrates the common use quite well. See http://fuse4bsd.creo.hu/localcgi/man-cgi.cgi?pidfile+3 , check out the "example" section. – Tim Post Sep 14 '10 at 10:06
  • @Tim, the man page contains an example but I have problems applying it to my daemon code. My daemon is differently structured. For example I don't use the function daemon(3). – Jan Deinhard Sep 14 '10 at 10:25

2 Answers2

5

The problem is that you want to give an error message before the daemon is spawned, and that you know the PID file after the daemon is spawned.

So you typically do the pidfile_open before the fork, which gives you a possibility to give an error message. After you forked, you know the pidfile and you can do pidfile_write.

Sjoerd
  • 74,049
  • 16
  • 131
  • 175
  • Why the fork anyway? daemon() forks, doesn' it? Why a second fork? – Jan Deinhard Sep 15 '10 at 20:47
  • Yes, daemon() forks. I meant that fork, there is no second fork. So you call pidfile_open(), daemon(), pidfile_write(), pidfile_close(). This way, you can output any errors from pidfile_open() to the terminal (before it is detached) and write the PID of the child, which is only known after calling daemon(). – Sjoerd Sep 16 '10 at 07:24
  • Oh, I thought you meant the example code from man pidfile. Because there a "second" fork is done after daemon(). Do you know why? – Jan Deinhard Sep 16 '10 at 12:05
  • 1
    @FairDinkumThinkum the second fork is needed on some systems to make sure that daemon is detached from terminal, it also makes the final daemon cease to be a session leader. Also see http://stackoverflow.com/questions/1740308/create-a-daemon-with-double-fork-in-ruby/1740314#1740314 – Ihor Kaharlichenko Dec 05 '11 at 20:40
1

You do the pidfile_open(3) before you go into background, so you can immediately report any problems. You don't write PID just yet, because your PID will change after daemon(3). pidfile_open(3) only locks the pidfile. After daemon(3) you can call pidfile_write(3) as you now have your final PID (daemon(3) forks internally). In the main process you cannot call pidfile_close(3), because this is the whole idea - by keeping the pidfile open and locked you let others know that you are still alive. The second fork is totally optional. It illustrates common behaviour that daemons spawn child/worker processes. If you don't use them you don't need this fork(). This fork() is there only to show that in such worker process you should close the pidfile, so it is only kept open and locked by the main process and not by the child.