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

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()).

Related

Why would a child process call getppid()? What can the PID of the Parent be used for?

When calling fork() the PID of the parent is saved in the child's PCB. In which case would it be useful for the child to know its parent's PID?
A process may wish to know if it was started by the init process at system startup, for example, and modify its behaviour accordingly.
Or, it may wish to communicate with its parent, say, to indicate something is complete, by sending a signal.

exit and wait function in UNIX (or LINUX)

I’m writing a program that simulates an unix-based operating system and I have some questions:
From unix.org
The wait() function will suspend execution of the calling thread
until status information for one of its terminated child processes is available, or until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process
Let's imagine there is process A with two child processes B and C. If B and C call the exit function, and then A calls the wait function, which exit status will be retrieved? The one from B or the one from C? Which first and why?
2.When the process is in the waiting state, it doesn't execute its code until for example the status information for one of the terminated child processes is available, is that right?
So it can't for example call a fork fuction while waiting, is that correct?
3.Are there any restriction on when a process can normally be killed in UNIX?
3.a. Are users authorized to kill root processes? (all of the root processes at will?)
wait() returns the PID of whatever child process exited. If two have exited, you must call wait() twice and check the returned PIDs. You shouldn't rely on the order.
Correct, the entire purpose wait() (without the WNOHANG option) is to block. So you cannot do anything else, apart from handling signals, in the waiting process.
I'm not sure exactly what you mean here, but I suspect the answer is mostly "no."
Users cannot kill root processes (at least, not without special configuration). Users also cannot kill processes owned by other users.
It is indeterminate whether B or C will be reported first.
While the process is in wait(), it can do nothing else (in a single-threaded process).
No restrictions for the most part. There are non-interruptible system calls, but the system tries to avoid getting processes hung in them.
No; a user can kill their own processes. User root can kill other people's process (in general); but no-one else can kill root's processes.

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.

reading the exit value of a defunct process

I have a dead process that is now in the defunct state which means that its parent process has not read its exit value. (and it is not going to read it)
I know that the exit value is stored somewhere in the kernel for the parent process to read but, is there a way for me to read that value if I am not the parent process ?
Ideally, I would be able to do this from a shell or an abritrary C/python/your-favorite-language program.
[edit]: This is not a question on how to reap the child or kill it. I do not care if it uses up a slot in the process table. I just want to know what its exit value is. i.e., I would like to read task_struct->exit_code in the kernel.
Mathieu
One thing you might be able to do is to send the parent SIGCHLD, which tells it that a child has died. If the program is of any quality, it will reap the process.
kill -s SIGCHLD parentpid
No. Attempting to call waitpid() for a process that is not one of the calling process's children will result in ECHILD. You will need to kill the parent process, causing the child to reparent to init, which will subsequently reap it.

Get the child PID after system()

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.

Resources