In programming, function invocation is designed to run in either synchronous or asynchronous mode. system() for instance, is a synchronous call. system(“something &”) is a ugly way to make system() kindda asynchronous because the execution of system command is put to background and thus system() returns immediately while return value is always 0.
To better control the system() process we’d better create another thread (pthread_create) or process (fork) to keep tracking the execution of that command, and in that thread/process we can do further process control over the command. For example, data validation, return value checking, sending notice to upper layer of the program…etc.
fork() is thus become very important to my c-cgi because certain operations are very time-consuming and without sophisticated adjustment, browser will be locked-up and wait till system command finishes. However, calling fork() is not enough. Let’s see how fork() is usually used in a program.
1: if(!fork())
2: { // start child process
3: setsid();
4: //do-something
5: exit(0);
6: }
Basically if fork() successes, there will be a duplicated process that you can’t miss by watching `ps` output. This is also the case when doing fork() in a cgi program, only that even if parent process returns (cgi finished,) browser’s loading status bar is not finished. The reason is quite simple.
∵ stdout and stderr of child process is duplicated from parent process, which is reserved for pipelining cgi output to browser webpage.
∴ browser is actually waiting for that piece of memory (duplicated in child process) being released.
Realizing this fact, we can easily modify the fork() code as follows,
1: if(!fork())
2: { // start child process
3: fclose(stdout);
4: fclose(stderr);
5: setsid();
6: // do-something
7: exit(0);
8: }
And thus your browser will no longer busy-waiting for the process. :)
