I am implementing my own shell, which requests pressing CTRL-Z to suspend foreground process. In order to not suspend my main process but only the child process, I have to catch the SIGTSTP by a handler in my main process and redirect it to my child process(which needed stop). But the kill function never return.
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
#include <sys/mman.h>
void handler(){
pid_t pid;
int status;
while((pid = waitpid(-1, &status, 0))>0){
printf("pid: %d has been reaped\n", pid);
}
}
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
//signal(SIGINT, send_signal);
signal(SIGCHLD, handler);
signal(SIGTSTP, send_signal);
}
void start_foreground_job(char** argv)
{
if( (fork()) ==0)
{
signal(SIGTSTP, SIG_DFL);
if((execve(argv[0], argv, NULL))<0)//envp
{
fprintf(stderr, "%s: Command not found.\n", argv[0]);
exit(0);
}
}
pause();
return;
}
int main(){
init_signals();
char* argv[] ={"/bin/sleep", "10", NULL};
start_foreground_job(argv);
printf("This line is what I expected after pressing CTRL-Z\n");
return 0;
}
When I try your code on my environment, the result is the same with you. I check son process's state after Ctrl+Z,
Before Ctrl + Z
ps -aux | grep sleep
16586 0.0 0.0 2016 412 pts/1 S+ 10:42 0:00 /bin/sleep 10
After Ctrl + Z
ps -aux | grep sleep
16586 0.0 0.0 2016 412 pts/1 T+ 10:42 0:00 /bin/sleep 10
Son process's state has changed from S -> T. It means father process has sent signal to son process successfully.
But son process doesnot exit, so your waitpid(-1, &status, 0) cannot return.
Option1: send kill signal to son process, and waitpid will get one return.
void send_signal(int signum)
{
if (pid)
{
printf("kill %d, signum %d\n", pid, signum);
//kill(pid, signum);
kill(pid, SIGKILL );
}
}
Option2: waitpid api has one option which can wait for stop state:
void handler()
{
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WSTOPPED)) > 0) {
printf("pid: %d has been reaped\n", pid);
break;
}
}
Please check below sw version, it works on my workstation.
int pid = 0;
void handler()
{
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WSTOPPED)) > 0) {
printf("pid: %d has been reaped\n", pid);
break;
}
}
void send_signal(int signum)
{
if (pid)
{
printf("kill %d, signum %d\n", pid, signum);
kill(pid, signum);
//kill(pid, SIGKILL );
}
}
void init_signals()
{
signal(SIGCHLD, handler);
signal(SIGTSTP, send_signal);
}
void start_foreground_job(char** argv)
{
pid = fork();
if (pid == 0) {
signal(SIGTSTP, SIG_DFL);
if ((execve(argv[0], argv, NULL)) < 0) { //envp
fprintf(stderr, "%s: Command not found.\n", argv[0]);
exit(0);
}
}
printf("son process pid is %d\n", pid);
pause();
return;
}
int main()
{
init_signals();
char* argv[] = {"/bin/sleep", "10", NULL};
start_foreground_job(argv);
printf("This line is what I expected after pressing CTRL-Z\n");
return 0;
}
Below is my test result:
./temp
son process pid is 29249
^Zkill 29249, signum 20
pid: 29249 has been reaped
This line is what I expected after pressing CTRL-Z
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.