Finding pid of background process from c prog - c

I am writing a program for creating a shell which handles basic functionalities such as executing basic commands,piping,redirection,executing background process.However i am not being able to kill a background process, i need to know the pid() of the background process so that i can send a kill call along with the pid.Any idea how to get the pid() of a background process from a c pogram?
For running the commands I am taking input from commandline into an array,parsing it and putting the command in arr[0] and the subsequent arguments in the subsequent indexes,i am taking the PATH of the system into another array and storing them as strings by using strtok and delim option as :,after this i am concatenating the path with the command,and then doing an execv().
I am stuck with this part where i have to kill a background process.Any suggestion would be extremely helpful.
Thanks in advance.

fork returns the PID of the child in the parent process, store it someplace and then use it to kill?

You should do something like this:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
pid_t pID = fork();
if (pID == 0) {
execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);
} else {
waitpid(pID, NULL, 0); // wait for child process
}
}

You can call getpid() (in the childprosses), or the pid of the child is returned to the parent when calling fork()

Related

How do I consistently find the PID of a program OR how do I send the kill shortcut to my terminal from a C script?

I'm answering my own question here because all of the other threads talking about this gave generally inefficient solutions to this problem[refer to title].
The most logical way to find the PID of a program is with getpid. However for some reason getpid command always gives you the PID that is two numbers behind the actual program ID it's about to be assigned. I'm sure someone more familiar with the linux kernel will be sure to explain why I'm an idiot in the comments below, so the reasoning for the -2 pid is probably down there.
Anyway, here's a reverse engineered c script(from MTU) that gives you the PID of the program.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
void main(void)
{
pid_t pid;
char fetch[50];
pid = getpid();
int pid2=pid+2;
sprintf(fetch, "echo hello world! my PID is %d", pid2);
system(fetch);
}
However for some reason getpid command always gives you the PID that is two numbers behind the actual program ID it's about to be assigned.
Well, getpid returns the PID of the current process.
How can it return the PID of a new process that doesn't exist yet? How could it possibly know?
The current process has a process ID. When you call system, it creates a child process, with its own process ID. Presumably the child process then creates another child to execute the command you passed to system.
By default the first child's PID will be the current process PID + 1. And the second child's PID will be the current process PID + 2. However, if either of those IDs are already in use (or you hit the maximum value of a pid_t and wrap around), this brittle logic will break completely.
If you want to get a child process' PID, call fork directly:
pid_t childpid = fork();
if (childpid < 0) {
perror("failed to fork");
exit(1);
}
if (childpid == 0) {
/* this path executes in the child process */
exec_command_in_child();
} else {
/* this path executes in the parent */
wait_or_kill_or_something(childpid);
}

Finding the PID of a process launched by exec() or system() in C program

I need to retrieve the PID of a process started by exec() or system(). I read on the subject and did my research, but I don't understand the suggestion of using fork() to do so.
Let's say I have the following code:
int pid = fork();
if (pid < 0 ) {
exit(1);
} else if (pid == 0 ) {
execlp("ls", "-a", NULL);
} else {
wait(0)
}
How to get the pid of the process started by execlp (or by system() if system was used instead)? I don't need to kill the process, I just need the PID to retrieve stats about it.
The exec* family of functions do not create new processes, instead they replace the execution context of the process they are called from, with the execution context of their target executable. The PID is maintained when this occurs.
#include <unistd.h>
#include <stdio.h>
int main(void) {
/* Normal execution */
puts("Hello");
/* Our programs contents get "replaced" by ls */
execlp("ls", "ls", "-l", NULL);
/* We never get here */
puts("World!");
}
fork, on the other hand, creates a new child process, which of course has its own PID. This child process carries on executing a copy of the same execution context it was spawned from; you can consider the execution to be "split" as soon as fork is called. fork returns 0 in the child process, and the PID of the child process in the parent (our original process).
The idea is to fork, and then use exec* to replace the execution context of the child process.
#include <unistd.h>
#include <stdio.h>
int main(void) {
pid_t pid;
/* Normal execution */
puts("Hello");
/* execution "splits" */
pid = fork();
if (pid == 0) {
/* Our child's execution context get "replaced" by ls */
execlp("ls", "ls", "-l", NULL);
} else {
/* still in the parent */
printf("Child PID is: %d\n", (int) pid);
}
/* We only get here in the parent */
puts("World!");
}
system is a wrapper around fork, exec* and and waitpid that blocks the calling process until the child process finishes its execution. The child's PID is not reported, because by the time parent can "act" again, the PID of the child is meaningless.
Error handling omitted for clarity of examples, but you should handle errors for fork, exec*, and wait* functions.

Using Signal Handlers to Pause/Resume a Child Process

I'm currently trying to experiment with signals in C by using them to control a child process created with the fork() method. Essentially, I have a child process running the "yes" command from the linux terminal (this command just prints "y" and a newline until it is terminated). I want to be able to pause/resume this process with CTRL-Z. This is what i've got right now:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
pid_t CHILD_PROCESS;
pid_t PARENT_PROCESS;
int isPaused;
void pause_handler(int signo){
if(!isPaused){
printf("Ctrl-Z pressed. Pausing child.\n");
isPaused = 1;
kill(CHILD_PROCESS,SIGSTOP);
}
else if(isPaused){
printf("\nCtrl-Z pressed. Resuming child.\n");
kill(CHILD_PROCESS,SIGCONT);
isPaused = 0;
}
}
int main(int argc, char** argv){
pid_t pid;
PARENT_PROCESS = getpid();
pid = fork();
if(pid == 0){
system("yes");
}
isPaused = 0;
if(pid > 0){
signal(SIGTSTP, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
CHILD_PROCESS = pid;
while(1){
if(signal(SIGTSTP,pause_handler) == SIG_ERR){
printf("Signal Failure");
}
}
}
}
When I run this, I can get "Ctrl-Z pressed. Pausing child." to print to console by pressing CTRL-Z, and I can get "Ctrl-Z pressed. Resuming child." to print to the console by pressing CTRL-Z again. However, it doesn't actually resume printing "y" over and over again. Any ideas as to why the child process isn't resuming?
As it turns out, system has an implicit fork call within it, so the PID that gets stored in CHILD_PROCESS ends up not actually being the child process, and instead an intermediate one.
From man 3 system:
The system() library function uses fork(2) to create a child process
that executes the shell command specified in command using execl(3) as
follows:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
system() returns after the command has been completed.
So, if we replace the system("yes") call with execl("/bin/sh", "sh", "-c", "yes", NULL), then we avoid this extra fork and the program functions as desired.
The only other issue is that, by I comment I found on this post, using printf within a signal handler is undefined behavior. Not an issue to worry about here, but something to keep in mind for future code!

Create child process on OSX and redirect stdin and stdout of child process to parent process?

I'm working on a C program in Xcode on OSX.
The (parent) program has to launch a new (child) process which receives its input via stdin and outputs results to stdout. So the parent writes data to the child process's stdin and the parent reads results from the child process's stdout.
On Windows I use CreateProcess to do the above, but I'm not sure how it's done on OSX in C.
I believe I'm supposed to use exec to start the process, but I don't see how I redirect stdin and stdout of the executable (child process) which exec starts. And from reading the manual it also looks like the child process will become the parent process if I use exec. The child and parent process has to run in parallel so that the parent process can write and read to the child process when it needs to.
Is there a kind OSX C expert out there who could give me a brief example of how the above is done?
Thanks
EDIT
I think I understand. But if the child process is an infinite while-loop which waits for input on stdin, then it won't turn into a "zombie", right?
The child process basically does this:
1. Read data from stdin (i.e. blocked until data is received)
2. Process data
3. Write result to stdout
4. Goto 1
After I read your post, I found this page:
http://www.jukie.net/~bart/snippets/popenRWE/popenRWE.c.html
However, I'm having a problem getting my .exe (child process) to launch
In a terminal, I would start the .exe like this:
./myApp.exe someParam1 someParam2 someParam3
The API looks like this:
popenRWE(int *rwepipe, const char *exe, const char *const argv[])
I'm guessing that the second argument should be:
const char* exe = "./myApp.exe";
and that the third argument should be:
char* p0 = "./myApp.exe";
char* p1 = "someParam1";
char* p2 = "someParam2";
char* p3 = "someParam3";
char** argv[4] = {p0, p1,p2,p3};
Am I right?
I'm including the source of a small library I've written a while ago. That should get you started. Fork / pipe / exec isn't really that easy (especially with all the variants of exec) and it took me a while too. So here goes:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "limbo.h"
int out_pipe[2], err_pipe[2];
int run_command(char *argv[], int *out_length, int *err_length){
pid_t pid;
int status = 0;
struct stat out_stat, err_stat;
pipe(out_pipe); //create a pipe
pipe(err_pipe);
if(!(pid = fork())) //spawn child
{
// Child. Close the read end of the pipe
close(out_pipe[0]);
close(err_pipe[0]);
// redirect stdout and stderr to the write end of the pipe
dup2(out_pipe[1], STDOUT_FILENO);
dup2(err_pipe[1], STDERR_FILENO);
status = execv(argv[0], argv); //child will terminate here
}
//Only parent gets here. Close write end of the pipe
close(out_pipe[1]);
close(err_pipe[1]);
//or wait for the child process to terminate
waitpid(pid, &status, 0);
fstat(out_pipe[0], &out_stat);
fstat(err_pipe[0], &err_stat);
*out_length = (int) out_stat.st_size;
*err_length = (int) err_stat.st_size;
return status;
}
int read_buffers(char *out_buffer, int out_length, char *err_buffer, int err_length){
out_buffer[read(out_pipe[0], out_buffer, out_length)] = 0;
err_buffer[read(err_pipe[0], err_buffer, err_length)] = 0;
return 0;
}
The comments in the code should help you to understand the code. Feel free to reuse.
Edit
In response to your comment:
The waitpid() call makes the parent process wait for the termination of the child process. If you want both processes to run in parallel, you need to get rid of waitpid() in the place that I use it. But be careful: without a call to one of the wait functions your child process will become a zombie once it finishes. It is your responsibility to keep an eye on your child process and to wait for it so the process can be cleaned up by the kernel.

ps command linux vs unix different behavior in c program

I have a simple c program that executes 'ps' and pipes it to 'grep', basically 'ps | grep x'.
the code goes more or less something like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
int pipefd[2];
int pid;
pipe(pipefd);
pid=fork();
if (pid == 0){
close(pipefd[1]);
dup2(pipefd[0], 0);
close(pipefd[0]);
execlp("grep", "grep", "b", (char *) 0);
}
else{
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);
execlp("ps", "ps", (char *) 0);
}
exit(0);
}
The problem that i have is that when i run this on unix (Solaris) is works perfect, but when i run this on (Debian) it executes properly but gives me an error message.
error message:
Signal 17 (CHLD) caught by ps (procps-ng version 3.3.3).
ps:display.c:59: please report this bug
I have try the same program running different commands like 'ls' and 'grep' with no problem on either os. What makes 'ps' different?
EDIT:
added the included libraries to the code.
When your program calls fork, it creates a parent process and a child process. In the child process fork returns 0 and in the parent it returns 1. Whenever a child process terminates, a SIGCHLD signal is sent to the parent process.
Now, in your case you call execlp in both the parent and child process, which replaces the running process image but does not change the relationship. This means that ps is your parent process and grep is your child process. Normally this would not matter, as programs ignore SIGCHLD by default, but ps catches all unknown signals and quits with the message you see there. You can see the relevant function in the source code for ps (or rather procps).

Resources