1

So I have this old, nasty piece of C code that I inherited on this project from a software engineer that has moved on to greener pastures. The good news is... IT RUNS! Even better news is that it appears to be bug free.

The problem is that it was designed to run on a server with a set of start up parameters input on the command line. Now, there is a NEW requirement that this server is reconfigurable (didn't see that one coming...). Basically, if the server receives a command over UDP, it either starts this program, stops it, or restarts it with new start up parameters passed in via the UDP port.

Basically the code that I'm considering using to run the obfuscated program is something like this (sorry I don't have the actual source in front of me, it's 12:48AM and I can't sleep, so I hope the pseudo-code below will suffice):

//my "bad_process_manager" int manage_process_of_doom() { while(true) { if (socket_has_received_data) { int return_val = ParsePacket(packet_buffer); // if statement ordering is just for demonstration, the real one isn't as ugly... if (packet indicates shutdown) { system("killall bad_process"); // process name is totally unique so I'm good? } else if (packet indicates restart) { system("killall bad_process"); // stop old configuration // start with new parameters that were from UDP packet... system("./my_bad_process -a new_param1 -b new_param2 &"); } else { // just start system("./my_bad_process -a new_param1 -b new_param2 &"); } } } 

So as a result of the system() calls that I have to make, I'm wondering if there's a neater way of doing so without all the system() calls. I want to make sure that I've exhausted all possible options without having to crack open the C file. I'm afraid that actually manipulating all these values on the fly would result in having to rewrite the whole file I've inherited since it was never designed to be configurable while the program is running.

Also, in terms of starting the process, am I correct to assume that throwing the "&" in the system() call will return immediately, just like I would get control of the terminal back if I ran that line from the command line? Finally, is there a way to ensure that stderr (and maybe even stdout) gets printed to the same terminal screen that the "manager" is running on?

Thanks in advance for your help.

4
  • 3
    Doing the kill() yourself, and fork() + exec() would give you more control over what happens in the even one of these tasks fails. Commented Oct 4, 2013 at 8:08
  • Good catch, looks like I have more man pages to read. Commented Oct 4, 2013 at 8:22
  • 1
    The way to ensure that you print the output to the same terminal is by appending 2>&1 to the command. This is a shell extension, not an argument. Commented Oct 4, 2013 at 8:24
  • @Troy, doing some preliminary research... how does one keep track of the pid of the process that I just exec()ed following a fork() call? How would I use kill() effectively? Commented Oct 4, 2013 at 8:27

1 Answer 1

1

What you need from the server:

Ideally your server process that you're controlling should be creating some sort of PID file. Also ideally, this server process should hold an exclusive lock on the PID file as long as it is still running. This allows us to know if the PID file is still valid or the server has died.

Receive shutdown message:

Try to get a lock on the PID file, if it succeeds, you have nothing to kill (the server has died, if you proceed to the kill regardless, you may kill the wrong process), just remove the old PID file.

If the lock fails, read the PID file and do a kill() on the PID, remove the old PID file.

Receive start message:

You'll need to fork() a new process, then choose your flavor of exec() to start the new server process. The server itself should of course recreate its PID file and take a lock on it.

Receive restart message:

Same as Shutdown followed by Start.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the help thus far. My last main concern is the fact that the "manager" that controls the stopping/starting is in fact a class in a much larger C++ program, which is multithreaded. There are reasons for this namely that the UDP port is actually used for other data packets. So one threads queues up UDP packets while another parses and does stuff with them. One action of a parsed packet is management of this C code. Are there any special considerations to make due to the multithreaded fork()/exec() call?
I've found this: linuxprogrammingblog.com/… so far which leads me to think that all I need to do is ensure that I open all sockets and fds with a certain flag and I should be safe...
system() also does a fork()+exec() or its equivalent, so if a program has worked with system() it will work with a manual fork()+exec().

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.