The situation is the following: I fork the process to open an html file with the default browser. Here is how it looks in my case:
if ((pid=fork())==0) {
execlp("/usr/bin/xdg-open", "xdg-open", url, NULL);
/*if execlp failed, exit the child*/
exit(0);
}
However, I want to get hold of the PID of the process (opened browser), so that I could close it later too. But I do not seem to know how could I get it. Please let me know if you have any suggestions.
You should already have the PID of the child process, the man page of fork() says:
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child.
So in the child process you detect the 0 and run your program, in the parent pid will be the actual PID of the child.
According to your comment what will then happen is that the xdg-open process - who's PID you now now will in turn start a browser and you have no direct access to the PID of that browser process.
At present the only thing I can think of doing is creating yet another child process that you run a command such as ps or pgrep in. You can then parse the output of that command to find the PID of the browser that is running as a child of the xdg-open. There is an example of reading the output of a child process here
fork() returns the pid of the child process to the parent.
In the child you can acquire it's own pid with the standard getpid().
pid_t child_pid = fork();
if (child_pid < 0) {
perror("fork");
// error handling
} else if (!child_pid) {
// child goes here
pid_t my_pid = getpid();
} else {
// parent continues here
}
Related
My program receives a string (a shell script's path) as input. Now I have to launch that shell script and find out the process id for it.
I'm using the system() function to launch a shell script and after that using popen() with ps -aef | grep "ShellScript" to get its PID.
It's being suggested to me that there's a better way to do it. The way I did it will give a wrong PID if multiple scripts are running at same time.
What is the correct way to get a PID for a given script name after launching it?
Firstly you should not use system().
A better approach would be using fork(), which returns a PID > 0 if you are in the parent process and return 0 if you are in the child.
Any other return satus is an error and errno is set accordingly.
When you are in the child process you should exec your command, while you should either wait for it in the parent one if you want to avoid to have a zombie process or handle SIGCHLD signal.
Always read man for better insight.
Here is a brief example
int pid = -1;
If((pid = fork()) > 0)
{
/* Parent process*/
wait(NULL);
}
else if(pid == 0)
{
/*Child process*/
execv(....);
exit (0);
}
else
{
/*Error*/
perror("fork()");
}
I'm currently trying to:
Execute a background process with a fork() call and execvp() inside the children.
If the call to execvp() was successful, adding the PID of the child process to a list.
If the call to execvp() returned -1 (error), do not add the PID to the list.
My problem is: if execvp() returns -1 (for instance, if the executable isn't found) I can't "communicate" with the parent proccess since I'm inside the child process in the fork(). And if I use waitpid() to wait for the child, I'm not running a background process (since I lose the concurrency).
I tried using WNOHANG and checking *status with (WEXITSTATUS(status) == 1) but it doesn't work (since the parent process executes "instantly" and doesn't know if the child has exited yet, or that's what I think)
My current code:
void background(char *vector[]) {
pid_t childp;
int status;
childp=fork();
if (childp==-1){
perror("Error using fork \n");
return;
}
if (childp==0) { //Child process
if (execvp(vector[0],vector)==-1) {
perror("exec");
exit(1);
}
}
waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status)) {
//Child exited
if (WEXITSTATUS(status) == 1) {
//Child exited with error
return;
}
}
if (insertProcess(childp,vector)==-1)
perror("Full list");
else
updateList();
}
The only solution I've found at the moment is inserting a sleep(1) call before waitpid (Source: https://stackoverflow.com/a/26617152/1339354 ), but this looks more like a hack than something well done. Any other ideas?
If you are using waitpid() with WNOHANG, be sure to especify the child process. If you don't, waitpid() returns status of the last child dead.
I'm not sure if you are trying to save on a list all process that was success. If you are trying it, why not instert always and then delete the process when they die? Control the signal SIGCHLD. In that, use the waitpid for look what process died and delete it in the list. Just deactivate the signal SIGCHLD when you create the process, insert the process on the list and then active again the signal.
In the below code, if there is a problem creating a child process or something happens to the child process what happens to wait(&status)?
pid_t pid;
int status;
if(pid=fork()){
printf("Parent Process\n");
wait(&status);
} else... child process here
If there is a problem creating a child process, fork will return -1, so this code will never wait.
If there's something happend to the child process, wait will return, and you can observe status.
If the child cannot be created, fork() will return with -1, you should look at errno after that. No error process is created here. Your code does not check this case.
If the child is created and dies, wait() will return the PID of the terminated process, the reason for the child's death is given in status. See the man page for wait on how to extract meaning from status.
I'm creating child processes in a for-loop. Inside the child process, I can retrieve the child PID with getpid().
However, for some reason when I try to store the value of getpid() into a variable declared by the parent process, the change is nullified when I check for it in the parent process. I'm assuming this has to do with some sort of process variable scope. Not really familiar with C, so can't be too sure.
Anyhow what is a way of storing the result of getpid() of a child PID (when called from the child process) into a variable in the parent process?
Or maybe another approach is storing fork() into a variable in the parent and calling some function on that variable to retrieve the child's PID? I don't know how to do this either, so if this is the better way, how would you do this?
fork already returns the child's pid. Just store the return value.
look at man 2 fork:
RETURN VALUES
Upon successful completion, fork() returns a value of 0 to the child process and
returns the process ID of the child process to the parent process. Otherwise, a
value of -1 is returned to the parent process, no child process is created, and
the global variable errno is set to indicate the error.
As mentioned in previous answer that "fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent process." So, the code can be written in this way:
pid = fork(); /* call fork() from parent process*/
if (0 == pid)
{
/* fork returned 0. This part will be executed by child process*/
/* getpid() will give child process id here */
}
else
{
/* fork returned child pid which is non zero. This part will be executed by parent process*/
/* getpid() will give parent process id here */
}
This link is very helpful and explains in detail.
if fork() is successfully created then it returns 0 value in the child process.
int main(void)
{
int id;
id= fork();
if(id==0)
{
printf("I am child process my ID is = %d\n" , getpid());
}
}
If you are calling fork in the following way:
pid = fork()
Then pid is in fact your child PID. So you can print it out from the parent.
Yes, the child process's pid is already returned with fork(), fork() is called once but return twice, different return value in parent and child process, so you can do this:
pid_t pid, pid_c;
pid = fork();
if (pid == -1) { // error
perror("Falied to fork");
} else if(pid == 0) { // execute in child process
// you can get child's pid by getpid() in child process:
pid_t tmp_pid_c = getpid();
execl("bin/ls", "ls", "./", NULL);
} else {
// you can also get child's pid that already returned by fork() in parent process
pid_c = pid;
}
There are two main functions to get the process id of parent process and child. getpid() and getppid()
So basically what i need is:
pid = fork();
if (pid == -1)
exit(1);
if (pid == 0)
{
// do stuff in child
}
else
{
// ONLY do stuff while child is running
}
would I need to create a tmp file right before the child exits saying that it is no longer running so the parent knows the child has exited when that file exists, or is there a simpler way to do this?
You can use waitpid to know if a child process is still running:
int status;
if (waitpid(pid, &status, WNOHANG) == 0) {
// still running
}
With WNOHANG, waitpid returns immediately so that the program can do something else.
When you have nothing to do other than waiting for the child process to terminate, call waitpid without WNOHANG.
The standard way to know that the child has terminated (and get its exit code) is to use the waitpid() system call.
Check wait () and waitpid () : http://linux.die.net/man/2/wait
Here is some more resource: http://users.actcom.co.il/~choo/lupg/tutorials/multi-process/multi-process.html#child_death_wait_syscall
There's a bunch of ways to do it. If you don't need to do anything with the child output, you can set a SIGCHLD handler to reap the child when it exits, and then forget about it in your main thread of execution. You can use the SIGCHLD handler to flag the exit of the child process via an IPC mechanism.
Or you can add a while loop that checks waitpid in your else clause. You would be doing discrete units of work between polls of the child state and you wouldn't get interrupted immediately on child exit.
Use the system wait() call if you just need to check if the child has stopped running.
int pid;
int status;
while (true)
{
pid = wait(&status);
if (pid < 0)
//keep waiting
else if (pid == 0)
//child is done
}