views:

44

answers:

3

I wrote a simple server in C and would like to have the same functionality calling it as other C daemons (such as calling it with ./ftpd start and closing that instance with ./ftpd stop). Obviously the problem I'm having is that I do not know how to grab the current instance of the running program. I can parse the options just fine (using getopt / optarg) but at the moment, ./my-program stop just starts a new instance vs. calling ./my-program start which starts it up fine.

The reason I want to do this is because another program will be signaling my server to stop, so a call like ./my-program stop is very simple, which can then stop the server loops and close all the open fd's. Thanks!

Is it possible to do this in the C program itself or is this usually handled externally?

+2  A: 

You will always run a separate process when running it with 'stop' argument. You need to find the running daemon and sending it a signal to stop it. When your deamon is started (option 'start'), you might want to store its pid somewhere so that when it is started with 'stop' option, it can retrieve the pid of the daemon and send it a signal to stop it. You can also parse the process table to find your daemon, but that will be more complex.

Benoit Thiery
I think this is what I was looking to do ... grab the pid on "start", and close that instance when "stop" is called. I'm not sure how to do that by the way, but I'm sure I can find it easily, so that's okay. The only problem I see with that, is that the instance called by "stop" will still be open correct? (since we are only closing the pid of the original instance). If you have suggestions other than this, I'm all for it, I thought this would be easy enough to implement but seems this is kind of "hackish".
Jack
The instance called by 'stop' can just smoothly exit once the daemon has stopped. You can also have a script or separate process to start and stop your daemon. Your daemon does not need to care about start and stop arguments and you don't need to start the daemon with stop to stop the real daemon in this case. This is probably cleaner.
Benoit Thiery
Thanks! This definitely helps.
Jack
+1  A: 

In most Linux distributions that I've come across, daemons are started and stopped via init scripts rather than direct invocation.

For example, on my Ubuntu box I can start and stop wicd by means of:

/etc/init.d/wicd start /etc/init.d/wicd stop

... which I think is what you want to do.

As some other people have noted, to stop a running process you will need to stash its PID somewhere, and then use that PID to send it a signal later on. You could implement this yourself in a script, but most Linux distros provide helper applications to take care of that for you e.g. start-stop-daemon(8) on Debian-derived platforms (Redhat distros have something similar, but I can't remember the application name off the top of my head).

So if it were me, I would write a script to handle the starting and stopping of your C daemon, and I would base that script on one of the others in /etc/init.d as ar mentioned above.

Tom Parkin
+2  A: 

Have a look at the killall command. The start within a script often just looks to see if an instance of the program already exists, and if it doesn't it starts it. The stop often just sends a signal to the service using the killall command.

Similar things that you may be interested in are editing or replacing the configuration files for a daemon and then sending the daemon the SIGHUP signal telling it that it should reread its configuration.

Another related topic is sending a daemon a particular message by calling the daemon's executable with some particular options. This is done this way because the interface that the messages are sent in can change and if it is the same program doing the sending and receiving it is hard to get out of sync. The method of sending messages can vary as well (Unix Domain Sockets, named pipe, editing a configuration file and sending SIGHUP, just about anything you could imagine). One other benefit of this is that the same input verification that the program uses when it runs as a daemon can be used before it sends the message, so if there is an error that the daemon would choke on the instance of the program that you are calling from the command line could go ahead and tell you on the terminal and refuse to pass this on to the daemon.

To find the PID of a running service either use a pid file (daemon creates a file in a certain location with its PID in it -- just like old lock files, or do it the same way that killall does -- look through /proc (which is platform specific).

nategoose
Thanks nate, I'm leaning towards not even implementing this in the program as it probably doesn't belong in it. As Tom mentioned above, these start | stop options are usually provided by shell scripts and not within the program itself. I just thought it would be easy if another program could just call it with a stop option. Killing is probably never good, so I will try to handle all the closes of fd's, stopping of loops, etc. some other way without relying on the "stop" signal from another program.
Jack
@Jack: The reason that I mentioned all of those different ways of sending messages to daemons was that I thought that you might have seen a couple of them in the past and then remembered them as though they were the same. The feel the same. Either way, `killall` can send any signal to a process and most signals can be handled, so the exit doesn't have to be ungraceful.
nategoose