Killing a process with C program - c

I'm writing a program that open a .txt file by vim and whenever i press CTRL+C the process will be killed. But the thing is i can't find the process's pid that i've just created and kill it. Can anybody help me?
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void ctrl_C(int sig){
system("kill -9 $(pidof id)");
printf("\n You pressed Ctrl + C,Good Bye \n");
exit(0);
}
int main(){
printf("I am Programmer \n");
pid_t id = system("gnome-terminal -- vi abcd.txt");
signal(SIGINT,ctrl_C);
while(1){}
}

There are multiple issues with your code:
system(3) does NOT return PID of child process, but instead waits for it to exit, and returns its exit code. You need to use the traditional fork+exec approach.
With child PID available, it's easier to call kill(2) than kill(1)
Better add sleep in a dead loop waiting for input. This reduces CPU load and your electricity bill.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
pid_t child_id;
void ctrl_C(int sig){
kill(child_id, 9);
printf("\n You pressed Ctrl + C,Good Bye \n");
exit(0);
}
int main(){
printf("I am Programmer \n");
pid_t child_id = fork();
if (child_id == 0) {
execlp("gnome-terminal", "gnome-terminal", "--", "vi", "abcd.txt", NULL);
return 255;
}
signal(SIGINT,ctrl_C);
while (1) {
sleep(1);
}
}

Related

Printf fails to print in parent and child after fork

I'm trying to use date and wc with pipes on CentOS. I'm not able to printf that I'm in parent or child. Any help is appreciated.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
/* pipe1.c - send information through pipe. */
void syserr(char* msg)
{
printf("%s", msg);
}
void child(int pfd[]){
dup2(pfd[1],1);
execl("/bin/date", "date", 0);
}
void main()
{
int pfd[2], i, pid;
char str[] = "Hello World!\n";
if (pipe(pfd) == -1)
syserr("pipe");
printf("pfd[0] = %d, pfd[1] = %d\n", pfd[0], pfd[1]);
pid=fork();
switch(pid) {
case -1:
syserr("fork");
case 0:
{
printf("I'm child'");
child(pfd);
}
default:{ /* parent only */
if(pid!=0)
{
printf("I'm parent'");
dup2(pfd[0],0); //input
execl("/bin/wc", "wc", 0);
}/*default*/
} /*switch*/
}
}
Remember that <stdio.h> is buffered, and stdout is generally line-buffered, at least when it is a terminal. See setvbuf(3)
So you should either end each of your printf format control string with a \n or call fflush(3) at appropriate places. In particular, do a fflush(NULL); before your fork and your execl.
Also use perror on failure (i.e. replace every call to syserr by perror) to understand how system calls are failing. See perror(3) & errno(3) & strerror(3).
BTW, your main is incorrectly declared. You should enable all warnings and debug info when compiling (e.g. compile with gcc -Wall -Wextra -g). Improve your code to get no more warnings. Then use the debugger gdb ...
Notice that to avoid zombie processes, your parent process should use some waiting system call like waitpid(2) or wait(2) or wait4(2)
Works now. I had to add close(pfd[0]); in child, and close(pfd[1]); in parent.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
/* pipe1.c - send information through pipe. */
void child(int pfd[]){
printf("I'm in child func\n");
close(pfd[0]);
dup2(pfd[1],1);
execl("/bin/date", "date", 0);
}
int main(){
int pfd[2], pid;
if (pipe(pfd) == -1) perror("pipe");
printf("pfd[0] = %d, pfd[1] = %d\n", pfd[0], pfd[1]);
fflush(NULL);
pid=fork();
switch(pid) {
case -1:
perror("fork");
case 0:
{
printf("I'm child\n");
child(pfd);
}
default:{ /* parent only */
if(pid!=0){
printf("I'm daddy\n");
close(pfd[1]);
dup2(pfd[0],0); //input
execl("/bin/wc", "wc", 0);
}/*default*/
} /*switch*/
}
return 0;
}

Using Scanf() in child process executed via execv not working

I am executing a really simple program which takes input in integer from user using scanf. I execute this program as a child program via fork() and execv.The child program never takes input from user.Any help would be appreciated.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
pid_t childpid;
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
execv("child",NULL);
exit(1);
}
else
{
printf("Parent process is terminating...\n");
return 0;
}
}
and the child code is
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int temp;
printf("This is Child Process. Child is going to sleep for 5 seconds\n");
sleep(5);
printf("Please enter an integer to terminate the process ");
scanf("%d",&temp);
printf("You entered %d ",temp);
printf("Child terminated");
return 0;
}
OUTPUT
[#localhost cascading]$ ./cascading
Parent process is terminating...
[#localhost cascading]$ This is Child Process. Child is going to sleep for 5 seconds
Please enter an integer to terminate the process You entered 12435[#localhost cascading]$ ^C
[#localhost cascading]$
I am running the code in fedora installed on a virtual machine.Thanks
Once the parent process finishes, control is returned to shell; and stdin could be closed.
To retain child's access to stdin, you can let the parent wait until the child is done.
So, in your parent:
else {
printf("Parent process is terminating...\n");
wait(NULL);
return 0;
}
You need to wait for child process to be finished, please modify your code like this
if(childpid == 0)
{
execv("child",NULL);
exit(1);
}
else
{
wait(); //wait for child
printf("Parent process is terminating...\n");
return 0;
}

Can this C code create zombie processes?

I am wondering if the following code can create zombies:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i=1;
pid_t p;
p = fork();
i++;
if(p!=0){
waitpid(p, NULL, 0);
}
printf("%d\n",i);
return 0;
}
So, the parent process calls the waitpid for the child process, which returns immediately if the child has not already exited. So, no zombies can arise so far. But, if the child exits before return 0; command this would be a zombie then? I am actually confused about it. Should the waitpid be the last line of code before the program terminates? Any help would be appreciated. Thanks!
The child only becomes a zombie if it ends and the parent doesn't call wait*() as long as itself lives on.
In the moment the parent also ends the child is reaped by the init process which will take care to call wait*() on the child, so it will finally end and with this leave the zombie state and disappears from the process list.
To provoke the child created in your example code to become a zombie modify the code for example as follows:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t p = fork();
if (p != 0)
{
waitpid(p, NULL, 0); /* See if the child already had ended. */
sleep(1); /* Wait 1 seconds for the child to end. And eat away the SIGCHLD in case if arrived. */
pause(); /* Suspend main task. */
}
else
{
sleep(3); /* Just let the child live for some tme before becoming a zombie. */
}
return 0;
}
Due to the two following facts:
the child sleeps for 3s so the parent's call to waitpid() most probably will always fail
the default handling of SIGCHLD is to ignrore it.
the code above in fact is the same as:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t p = fork();
if (p != 0)
{
pause(); /* Suspend main task. */
}
else
{
sleep(3); /* Just let the child live for some tme before becoming a zombie. */
}
return 0;
}
I found a simple way to create a zombie process and test it using ps -e
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void main()
{
pid_t pid;
pid = fork();
//parent sleeps while the child has exited
//not an orphan since parent still alive
//child will be still present in process table
if(pid==0)
{//child
exit(0);
}
else
{//parent
sleep(15);
}
}
run ps -e while within the 15 seconds...
you will see
6454 pts/2 00:00:00 a.out < defunct >

Reading from FIFO(named pipe) in While loop without body

im trying to make a tic tac toe game with server-client in c.
On the server side i have to read from FIFO(named pipe) 2 pids.
so i made a loop that run until the read (from fifo) return value different from zero(mean that the client wrote pid to the fifo).
I have to say that for some reason, on my laptop it's not working and on my buddy laptop it's working. The same code!! I have no clue why this is happening.
And when i add a body to the first while loop and put a printf("1"); in it. it's work and the pid1 reads the pid from the FIFO.
The code of the server:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
void main()
{
int fd,shmid;
key_t shmkey;
void *shm_add;
pid_t pid,pid1=0,pid2=0;
mkfifo("fifo_clientTOserver",400);
fd=open("fifo_clientTOserver",O_NONBLOCK | O_RDONLY);
pid=fork();
if(pid==0)
{
while(read(fd,&pid1,sizeof(pid_t))==0); //(1)
}
else
{
wait();
while(read(fd,&pid2,sizeof(pid_t))==0)
{
if(pid2!=pid1)
break;
}
remove("fifo_clientTOserver");
}
printf("\nfirst pid= %d\nsecond pid= %d\n",pid1,pid2);
}
The code of the Client:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdbool.h>
void my_handler(int signum);
bool over=false;
int board[3][3]={{0,0,0},{0,0,0},{0,0,0}};
char tav;
static bool first=false;
void main()
{
int fd;
pid_t pid1=getpid();
signal(SIGUSR2, my_handler);
fd=open("fifo_clientTOserver",O_WRONLY);
write(fd,&pid1,sizeof(pid_t));
printf("%d\n",pid1);
while(!over);
}
void my_handler(int signum)
{
char geth;
printf("1");
//Check if the signal is SIGUSR2.
if (signum == SIGUSR2)
{
if(!first)
{
tav='x';
printf("x");
first=true;
}
else
{
tav='c';
printf("c");
}
}
}
It's really weird and i dont know how to deal with it!
When i change line (1) to while(read(fd,&pid1,sizeof(pid_t))==0){printf("1");}
it's working and pid1 get the value.
Please help me.
man read:
If some process has the pipe open for writing and O_NONBLOCK is set,
read() shall return -1 and set errno to [EAGAIN].
So, your while loop breaks without anything read.
In any event, busy waiting is bad. Drop the O_NONBLOCK or use
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
select(fd+1, &readfds, NULL, NULL, NULL);
before the read().
When you are constantly checking something within a loop, non-blocking and other parallel activities are starved. This busy waiting can be avoided by sleeping between checks or using I/O multiplexing (select).
while( !AreWeThereYet() ) { GetSomeSleep(); }

Using fork() for split process- what's wrong with the program

I'd really love your help with understanding why doesn't the process reach the "son process" after using fork() command. I'm trying to write a program that runs another program, but It seems that the program dosen't even reach the son process. I can tell that since "son process" is not being printed to the screen, and I really wonder why.
Here's a sketch of the code- I can't even check if it is alright since as I said, it doesn't even reaching the son process, I always get "son exited with error".
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <assert.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <time.h>
#define MAXARGV 5;
int main() {
char* cmd;
int child_status;
char* s;
char** argv;
int counter;
cmd= (char*) calloc( 5, sizeof(char)*20);
s=(char*) calloc(1,sizeof(char)*20);
argv=(char**) calloc(5, sizeof(char*)*20);
printf("Please write a command\n");
gets(cmd);
counter = 0;
while (strcmp(cmd, "exit") != 0) {
int pid = fork();
if (pid == 0) {
printf("son process");
while (sscanf(cmd, "%s", s) == 1) {
strcpy(argv[counter], s);
counter++;
}
execv(argv[0], argv);
printf("the command is not legal");
assert(0);
}
else {
if (wait(&child_status) == -1) {
printf("error waiting for pid=%d\n", pid);
exit(-1);
}
if(WIFEXITED(child_status)!=0)
printf("son status=%d\n", WEXITSTATUS(child_status));
else
printf("son exited with error\n");
}
printf("Please write a command");
gets(cmd);
}
free(s);
free(cmd);
free(argv);
printf("here as well");
return 1;
}
The program reaches the printf("son process") just fine, but that just puts the string in a buffer inside the process and since you didn't fflush() it, it doesn't make it to the screen and is discarded with the rest of the process' memory in the exec call. Note, that stdout is normally line-buffered, so if you had newline there, it would auto-flush. Also stderr is by default unbuffered and more suitable for debug prints (fprintf(stderr, "child process")).
You are trying to assemble the command read from standard input in argv, but it only has memory for the actual arguments given to you, so you overrun this memory and get segmentation fault.
if WIFEXITED gives zero, you should use WIFSIGNALED and WTERMSIG to confirm that the error is indeed SIGSEGV.
assert(0) is not a good way to terminate process after error. exit(1) is. Assertions are only for conditions that indicate bug in the code itself if they happen and are often eliminated (by defining NDEBUG) from production code.

Resources