27

I want to launch a process from within my c program, but I don't want to wait for that program to finish. I can launch that process OK using system() but that always waits. Does anyone know of a 'non-blocking' version that will return as soon as the process has been started?

[Edit - Additional Requirement] When the original process has finished executing, the child process needs to keep on running.

Simon Hodgson
  • 563
  • 3
  • 6
  • 12

6 Answers6

23

One option is in your system call, do this:

 system("ls -l &");

the & at the end of the command line arguments forks the task you've launched.

Doug T.
  • 64,223
  • 27
  • 138
  • 202
16

Why not use fork() and exec(), and simply don't call waitpid()?

For example, you could do the following:

// ... your app code goes here ...
pid = fork();
if( pid < 0 )
    // error out here!
if( !pid && execvp( /* process name, args, etc. */ )
    // error in the child proc here!
// ...parent execution continues here...
FreeMemory
  • 8,444
  • 7
  • 37
  • 49
  • hmmm, doesn't seem to be working for me. I think the problem might be that my program (it's a CGI app) exists as soon as it's called execvp - will this kill off the child process? Also... the code after execvp appears to be being run twice. – Simon Hodgson Jun 16 '09 at 16:37
  • Simon, can you place a code sample here? What might happens is the parent has exit as soon as child process had been forked. Have you used waitpid(chld_pid) as proposed by Mr./Ms. FreeMemory? – SashaN Jun 16 '09 at 16:43
  • @Simon: if the code after execvp() appears to run twice, most likely it means that the execvp() failed and the error handling for it didn't stop things going awry (return or exit). In a CGI program, do you know what the PATH is set to? It is probably more spartan than you expected. – Jonathan Leffler Jun 16 '09 at 16:50
  • OK, I've read up some more about fork() and now understand the above example better and know why some of the code was being run twice. It's a bit difficult to see what's happening, but I think the forked process is being killed off when the original process exits. – Simon Hodgson Jun 16 '09 at 17:08
  • @Simon: To make the child process live on, couldn't you trap SIGHUP? – FreeMemory Jun 16 '09 at 17:22
9

The normal way to do it, and in fact you shouldn't really use system() anymore is popen.
This also allows you to read or write from the spawned process's stdin/out

edit: See popen2() if you need to read and write - thansk quinmars

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
1

You could use posix_spawnp() function. It's much similar to system() than the fork and exec* combination, but non-blocking.

0

In the end, this code appears to work. Bit of a mis-mash of the above answers:

pid = fork();

if (!pid)
{
    system("command here &");
}

exit(0);

Not quite sure why it works, but it does what I'm after, thanks to everyone for your help

Simon Hodgson
  • 563
  • 3
  • 6
  • 12
  • 1
    It works, but it's not really what you want to do. system() actually forks an instance of a shell, and passes the shell the command you want to execute. So basically, what you're doing is as follows: fork(), fork(), execl( "/bin", "sh", "command_to_run &" ). Sure, it works, but it's doing a lot more work than it ought to. – FreeMemory Jun 16 '09 at 18:22
  • 3
    why the extra fork()? Can't you just use the system("... &"); call? – Carson Myers Jun 16 '09 at 21:13
-2

How about using "timeout" command if you are looking for your command to exit after a specific time:

Ex: system("timeout 5 your command here"); // Kills the command in 5 seconds if process is not completed