Get the child PID after system() - linux

As far as I understand, the system() call uses internally fork() and exec() but encapsulates them for a easier handling.
Is it possible to get the PID from the child process created with the system() call?
Aim: I want to be able to SIGINT any child process after a certain timeout. I could rebuild the system() function by using fork() and exec(). But all I need is the child's PID and perhaps there is shortcut by using system()?

Typically, system() is a synchronous operation. This means it won't return until the child has exited, i.e. there is no valid PID for the child process when system() returns, since the child process no longer exists.

There's no way (that I know of) when using system(). Besides, with system() there's the additional step of launching a shell which will execute your command, making this a tad more difficult. You're probably better off replacing it with fork() and exec().

I had this problem. Solved it by:
int syspid,status;
pid_t ppid=getpid();
syspid=ppid+1
status=system(argv[1]); //here argv1 was another program;
This might not always work, but most of the time the system()'s PID is the parent's pid +1 (unless you have multiple forks).

However, there is a way of doing what you want via the /proc file system. You can go through process directories (directory names are PIDs) and check the "status" files. There's a PPid entry in each of them specifying the parent pid.
This way, if you get a "status" file which specifies the PID of your process as PPID, then its folder name in /proc file system is the value you are looking for.

Related

How to get the pid of a process started using system call?

In a C program, in main I am calling a system function using system().
Now I want the pid of that process started by system().
Is there any way to get that pid ?
No, and in general it's not useful. When the call of system() returns to your program, the child process has terminated and been reaped, so there's no process (not even a zombie process) for it to reference.
If you need to start a process and retain its PID, you'll need to fork() a child yourself (noting the returned value in the parent), and in the child, exec() the command. In the parent, you now have the PID, and can use it (e.g. in waitpid()).

Does the Linux scheduler prefer to run child process after fork()?

Does the Linux scheduler prefer to run the child process after fork() to the father process?
Usually, the forked process will execute exec of some kind so, it is better to let child process to run before father process(to prevent copy on write).
I assume that the child will execute exec as first operation after it will be created.
Is my assumption (that the scheduler will prefer child process) correct. If not, why? If yes, is there more reasons to run child first?
To quote The Linux Programming Interface (pg. 525) for a general answer:
After a fork(), it is indeterminate which process - the parent or the child - next has access to the CPU. (On a multiprocessor system, they may both simultaneously get access to a CPU.)
The book goes on about the differences in kernel versions and also mentions CFS / Linux 2.6.32:
[...] since Linux 2.6.32, it is once more the parent that is, by default, run first after a fork(). This default can be changed by assigning a nonzero value to the Linux-specific /proc/sys/kernel/sched_child_runs_first file.
This behaviour is still present with CFS although there are some concerns for the future of this feature. Looking at the CFS implementation, it seems to schedule the parent before the child.
The way to go for you would be to set /proc/sys/kernel/sched_child_runs_first to a non-zero value.
Edit: This answer analyzes the default behaviour and compares it to sched_child_runs_first.
For the case where the child calls exec at the first opportunity you can use vfork instead of fork. vfork suspends the parent until the child calls _exit or exec*. However, once it calls exec the child will be suspended if code has to be loaded from disk. In this case, the parent has a good chance to continue before the child does.

making parent process wait till child has called exec

In linux, after calling fork(), my child process is going to call exec soon. Is there a way for the parent process to wait() and not do anything till the child has exec'ed?
Thanks.
There is no (API) way for the parent to know that the child is performing an exec().
But there is a nice pipe-trick: have the child inherit a filedescriptor (for a pipe) and (before the fork() ) set the close-on-exec flag for the pipe. The parent will be notified by an EOF on the pipe when it is closed by the exec().
Please note that this does not need any collaboration from the child.
Use vfork() instead of fork(). That causes the parent to be suspended until the child either exits or calls one of the execve() family of functions.
You need to use waitpid using the process ID returned from the fork call that is returned to the parent.
EDIT
Or if you mean that you want to know that the child is about to call exec use pause in the parent. Get the child to call kill with a suitable signal to the parent (whose process ID can be obtained from getppid). USR1 signal might be useful to use. Do this just before the exec.

parent process after child does an exec

I have a scenario in which after the fork the child executes using the excele() command
a linux system command in which its executes a small shell script .
And the parent does only a wait() after that . So my question is , does the parent executes
wait after an execle() which the child process executes ?
Thanks
Smita
I'm not too sure what you're asking, but the parent is in a wait() system call it will wait there until any child exits. There are other things like signals that will take it out of the exit too.
You do have to be careful in the child process that you don't accidently fall through into the parent code on error.
This (a child process doing some execve after its parent fork-ed, and the parent wait- or waitpid-ing it) is a very common scenario; most shells are working this way. You could e.g. strace -f an interactive bash shell to learn more, or study the source code of simple shells like sash
Notice that after a fork(2) syscall, the parent and the child processes may run simultanously (e.g. at the same time, especially on multi-core machines).

What happens when a process is forked?

I've read about fork and from what I understand, the process is cloned but which process? The script itself or the process that launched the script?
For example:
I'm running rTorrent on my machine and when a torrent completes, I have a script run against it. This script fetches data from the web so it takes a few seconds to complete. During this time, my rtorrent process is frozen. So I made the script fork using the following
my $pid = fork();
if ($pid == 0) { blah blah blah; exit 0; }
If I run this script from the CLI, it comes back to the shell within a second while it runs in the background, exactly as I intended. However, when I run it from rTorrent, it seems to be even slower than before. So what exactly was forked? Did the rtorrent process clone itself and my script ran in that, or did my script clone itself? I hope this makes sense.
The fork() function returns TWICE! Once in the parent process, and once in the child process. In general, both processes are IDENTICAL in every way, as if EACH one had just returned from fork(). The only difference is that in one, the return value from fork() is 0, and in the other it is non-zero (the PID of the child process).
So whatever process was running your Perl script (if it is an embedded Perl interpreter inside rTorrent then rTorrent would be the process) would be duplicated at exactly the point that the fork() happened.
I believe I found the problem by looking through rTorrent's source. For some processes, it will read all of the output sent to stdout before continuing. If this is happening to your process, rTorrent will block until you close the stdout process. Because you're forking, your child process shares the same stdout as the parent. Your parent process will exit, but the pipe remains open (because your child process is still running). If you did an strace of rTorrent, I'd bet that it'd be blocked on this read() call while executing your command.
Try closing/redirecting stdout in your perl script before the fork().
The entire process containing the interpreter forks. Fortunately memory is copy-on-write so it doesn't need to copy all the process memory in order to fork. However, things such as file descriptors remain open. This allows child processes to handle them, but may cause issues if they aren't closed appropriately. In general, fork() should not be used in an embedded interpreter except under extreme duress.
To answer the nominal question, since you commented that the accepted answer fails to do so, fork affects the process in which it is called. In your example of rTorrent spawning a Perl process which then calls fork, it is the Perl process which is duplicated, since it was the Perl process which called fork.
In the general case, there is no way for a process to fork any process other than itself. If it were possible to tell another arbitrary process to go fork itself, that would open up no end of security and performance issues.
My advice would be "don't do that".
If the Perl interpreter is embedded within the rtorrent process, you've almost certainly forked an entire rtorrent process, the effects of which are probably ill-defined at best. It's generally a bad idea to play with process-level stuff in an embedded interpreter regardless of language.
There's an excellent chance that some sort of lock is not being properly released, or that threads within the processes are proceeding in unintended and possibly competing ways.
When we create a process using fork the child process will have the copy of the address space.So the child also can use the address space.And it also can access the files which is opened by the parent.We can have the control over the child.To get the complete status of the child we can use wait.

Resources