views:

706

answers:

9

I have a service, say foo, written in C++, that runs as root. There is the usual scrip, /etc/init.d/foo start|stop|restart.

At certain times, foo needs to reload itself. Normally after an upgrade has finished. But doing things like:

system("/etc/init.d/foo restart")

doesn't work since as soon as restart kills foo, the system() call obviously gets killed as well, and the restart script never executes to completion.

Is there another call I can use instead of system() that runs asynchronously as a sibling to the calling process, instead of creating a synchronous child?

Thanks!

+8  A: 

Have you considered the exec[*] family yet? Here's one -- execve.

dirkgently
Thanks. The other trick I had to research was to call fcntl() to set the FD_CLOEXEC on the server listening port. Otherwise the exec'd() app would inherit the original socket and would cause me grief.
Stéphane
+5  A: 

how about fork() followed by exec()?

Eric Petroelje
No need to fork in this case, just exec().
Juliano
+1  A: 

Combining the two answers so far, use a fork-exec.

Adam Rosenfield
+8  A: 

You could put it in inittab and let init worry about restarting the process when it exits for any reason. That would also take care of automatic restarts if your process happens to crash or assert() or otherwise exit unexpectedly.

Then, to handle your use case, the process would simply terminate itself.

Ori Pessach
+1  A: 

To add to what Ori has already said, some Linux distros still use initab, but Ubuntu and possibly others have switched to /etc/event.d. You put a file in there (copy and edit one of the existing ones) then start the daemon with "sudo start ssh_tunnel" or whatever your file is called.

Then when you need it to restart, you can just kill it with a signal, and the system will restart it. Or it could decide on its own that it's time to restart, by calling "exit(0);" or whatever.

Paul Tomblin
A: 

Look at the man page for inittab.

It describes how the system will auto restart your processes if it dies (respawn).

With this set up correctly all you service has to do is exit and the system will take care of the re-start (respawn) for you auto-magically.

Martin York
+1  A: 

exec*() by itself on the original command line should do the trick. You can probably omit the fork, `cause then you have two copies running which you don't need, and the original copy then needs to exit.

But also look at inittab and event.d depending on your distro, to see if it will do what you need in a better way.

Rob K
+1  A: 

Consider implementing

/etc/init.d/foo reload

for your daemon (pretty standard judging by a grep of my Debian box).

This is typically done by sending the process a SIGHUP signal; the daemon should have a signal handler which catches this and reloads any configuration.

If the process knows it needs to reload it can just signal itself.

If you really do need to restart to pick up new libraries then go with exec*()

timday
+1  A: 

A third possibility to what Ori and Paul have suggested would be to use daemontools. It is more portable though less likely to be available. You create a script called /service/foo/run and daemontools will respawn your service whenever it exits.

http://cr.yp.to/daemontools.html

bstpierre