BorisSchaeling / boost-process

Boost.Process is a library to manage system processes
Boost Software License 1.0
32 stars 20 forks source link

Keep child alive when parent application terminates #13

Closed JaFarmland519 closed 8 years ago

JaFarmland519 commented 8 years ago

Howdy. I am using Boost Process to run a child process (command called DreamDaemon, game server) from a parent C++ application, obviously. I was wondering if there was a way to keep the child DreamDaemon process when my C++ application closes.

e.g. I run the following code:

child child = execute(set_args(argsChild), close_stdin());

With argsChild as my command line arguments

DreamDaemon will start up, and the game will start. However, if I terminate my own application (control+c), it kills the DreamDaemon instance with it. Not entirely sure if this is making sense, so if you can't follow, I'll try to explain it another way.

Is it possible to keep the DreamDaemon process running even when my parent app is closed? I would have thought that since I just execute the command, it is hands off? Does this have something to do with the child object being killed when my application is terminated? Any info you can give would be appreciated, thanks!

BorisSchaeling commented 8 years ago

boost::process::child does not terminate a child process once an object of this type is destroyed (resources are cleaned up like a HANDLE to the child process on Windows; but this does not terminate a child process).

Do you have this problem on Windows or Linux or both?

Are you by any chance using a pipe or another shared resource between your parent and child process (anything which will get closed when your parent process exits and which will then confuse the child process)?

JaFarmland519 commented 8 years ago

Oh, I should have specified (sorry) - I am using Debian 8.2. The server is only running on Linux, and I rely on things like Unix Domain Sockets, so I think Windows is a no-go.

I am looking through the code, and I don't see anything that would confuse the child. I've tried to keep the parent and child separate to the best of my ability, and all the parent needs to do is just start the child. I am doing close_stdin (see first post with the code); I can try to close stdout and stderr when I get home from school later, if maybe that is causing this.

BorisSchaeling commented 8 years ago

Do the StackOverflow questions (and answers) Are child processes created with fork() automatically killed when the parent is killed and How to make child process die after parent exits help?

JaFarmland519 commented 8 years ago

I took a look at what you linked, but I am trying to keep the child alive once the parent dies, not kill it when the parent dies. I thought fork transfers ownership to the system, but my application isn't for some reason

BorisSchaeling commented 8 years ago

I referred you to StackOverflow so you can check whether your programs do something similar. After all your programs seem to do something to make the child process die after the parent exits - this isn't default behavior on Linux as the questions at StackOverflow prove. :)

JaFarmland519 commented 8 years ago

Ah yeah, it is a bit strange. Let me run through my code again and see if something is up. Do you think closing all of the streams would help anything?

BorisSchaeling commented 8 years ago

I don't think so. If the child process depends on the streams to be open, I would assume you create even more havoc if you close the streams. :)

JaFarmland519 commented 8 years ago

@BorisSchaeling So I think I have an idea of what to do now. I did some pretty good research and came across setpgid. So I can now run setpgid(1, child.pid) and only when the application calls EXIT, it will transfer the process to the system. However, if I control + c the parent without successfully exiting, it won't do this. Pretty strange, so I must be missing something important, but it is progress.

JaFarmland519 commented 8 years ago

Alright, for future people who have this problem, here is my working code. I can terminate the parent in any way, and the child will still be assigned to the system when killed, thus staying alive:


        child child = execute(set_args(argsChild), close_stdout(), close_stderr(), close_stdin());

        // Set process parent to itself so that child can stay alive when parent dies
        // This takes effect once this (parent) is terminated or crashed
        if(setpgid(child.pid, child.pid) != 0){ // Returns 0 if successful
                std::cout << "Error setting parent id to child: " << strerror(errno) << std::endl;
        }

Thanks @BorisSchaeling for the work and help you've provided :+1:

nikhilbaby2000 commented 6 years ago

It been few years since the question, but may be this will be helpful for someone else. I wanted to keep the child alive but dont want to keep the parent alive. At the end of every child process, i was recursively calling the same command - in symfony.

How did i achieved this: called the console commad: php app/console my_command

in the begining itself: $myPid = getmypid(); pcntl_fork(); passthru("kill {$myPid}");

After the command is completed, just before exiting i again called:

php app/console my_command

This way the command is a linked list of same commands.

This way, all the subsequent children will be alive, but the parent will not be. pcntl_fork(); This will Forks the currently running process, which in-turn makes its parent as PID: 1

My objective was to run a cron-process continuously as a console command!

BorisSchaeling commented 6 years ago

For future readers: The latest (and official) version of Boost.Process is found at https://github.com/klemens-morgenstern/boost-process/.