why child can't send signal to parent - c

parent:
volatile int signalval = 0;
void signal_handle_c(int sig_num)
{
printf("child SIGUSR1 ok\n");
signalval = 1;
};
int main(int argc,char**argv){
struct sigaction act, oldact;
act.sa_handler = signal_handle_c;
act.sa_flags = SA_NOMASK;//SA_ONESHOT |
pid_t pid=fork();
if (pid < 0)
printf("error in fork!");
else if (pid == 0) {
printf("exec child!%s\n",argv[1]);
int res = execl(argv[1], "testc", NULL);
printf("res=%d", res);
}
else {
sleep(3);
sigaction(SIGUSR1, &act, &oldact);
printf("now parent\n");
}
waitpid(pid,NULL,0);
return 0;
}
child:
volatile int signal_pipe_end = 0;
void signal_handle_c(int sig_num)
{
printf("child IGUSR1 ok\n");
signal_pipe_end = 1;
};
int main(int argc, char *argv[])
{
printf("now child run!");
while (1)
{
printf("now child send siganl\n");
kill(getpid(), SIGUSR1);
sleep(1);
}
}
parent try to receive the SIGUSR1 signal from child.but none!
run result:
exec child!./testc
now child run!now child
now parent
i hope can printf "child SIGUSR1 ok".
why child "kill" send signal fail.

Related

Timer disarms when interval is too small

Timers seem to disarm after process is resumed (SIGCONT) ONLY when interval is too small.
I use timer_create with CLOCK_REALTIME.
My linux distribution is ubuntu 20.04.1
This is the code that shows the problem
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
volatile siginfo_t sigInfo;
void childFunction();
void parentFunction(pid_t pid);
void ignoreChild();
void signalFunction(int signo, siginfo_t* SI, void* data);
int main(int argc, char* argv[])
{
ignoreChild();
pid_t pid;
pid = fork();
switch(pid)
{
case -1:
{
perror("Error in fork!\n");
exit(EXIT_FAILURE);
}
case 0:
{
childFunction();
exit(EXIT_SUCCESS);
}
default:
{
parentFunction(pid);
break;
}
}
return 0;
}
void signalFunction(int signo, siginfo_t* SI, void* data)
{
sigInfo = *SI;
}
void parentFunction(pid_t pid)
{
struct sigaction sa;
struct timespec sleepTime = { .tv_sec = 1, .tv_nsec = 0};
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = signalFunction;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("Error in sigaction!\n");
exit(EXIT_FAILURE);
}
//---- for blocking
sigset_t set = {0};
if (sigaddset(&set, SIGCHLD) == -1)
{
perror("Error in sigaddset!\n");
exit(EXIT_FAILURE);
}
while (1)
{
if (pause() == -1)
{
if (errno == EINTR)
{
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
{
perror("Error in sigprocmask!\n");
exit(EXIT_FAILURE);
}
if (sigInfo.si_status == SIGSTOP)
{
printf("Child received SIG_STOP signal\n");
nanosleep(&sleepTime, NULL);
kill(pid, SIGCONT);
}
if (sigInfo.si_status == SIGCONT)
{
printf("Child received SIGCONT signal!\n");
}
if (sigInfo.si_code == CLD_EXITED)
{
printf("Child is dead!\n");
break;
}
if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
{
perror("Error in sigprocmask2!\n");
exit(EXIT_FAILURE);
}
}
}
}
}
void ignoreChild()
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDWAIT;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("Error in sigaction!\n");
exit(EXIT_FAILURE);
}
}
void childFunction()
{
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGSTOP;
struct timespec timeForTimer = { .tv_sec = 1, .tv_nsec = 0}; // set time for timer here!
struct itimerspec ts = { .it_interval = timeForTimer, .it_value = timeForTimer };
timer_t timer;
if (timer_create(CLOCK_REALTIME, &sev,&timer) == -1)
{
perror("Error in timer_create!\n");
exit(EXIT_FAILURE);
}
if (timer_settime(timer, 0, &ts, NULL) == -1)
{
perror("Error in timer_settime!\n");
exit(EXIT_FAILURE);
}
struct timespec timeToWaitInLoop = { .tv_sec = 0, .tv_nsec = 300000000};
for (int i=0; i<1000; ++i)
{
printf("I'm working!\n");
nanosleep(&timeToWaitInLoop,NULL);
}
}
When I set timeForTimer to 3 seconds the program works correctly, for 2 seconds it still works but for 1 second it doesn't.
To compile:
gcc -Wall main.c -lrt
This is shorter example
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGSTOP;
struct timespec timeForTimer = { .tv_sec = 1, .tv_nsec = 0}; // set time for timer here!
struct itimerspec ts = { .it_interval = timeForTimer, .it_value = timeForTimer };
timer_t timer;
if (timer_create(CLOCK_REALTIME, &sev,&timer) == -1)
{
perror("Error in timer_create!\n");
exit(EXIT_FAILURE);
}
if( timer_settime(timer, 0, &ts, NULL) == -1)
{
perror("Error in timer_settime!\n");
exit(EXIT_FAILURE);
}
struct timespec timeToWaitInLoop = { .tv_sec = 0, .tv_nsec = 300000000};
for (int i=0; i<1000; ++i)
{
printf("I'm working! (PID) %d\n", getpid());
nanosleep(&timeToWaitInLoop,NULL);
}
}
In above example only one SIGSTOP signal occured. After sending SIGCONT with command kill -18 <pid> there was no more SIGSTOP signals.It looks like my timer disarmed.

Why can't I catch SIGCHLD every time after fork?

I am trying to create 4 child processes and until the children die, parent should wait. I wrote a program but when I run this code, 1 out of 10, it can't catch the SIGCHLD from every child and my program goes to infinite loop after. It happens really rare but still..
Could you tell me why and how can I fix it?
Here is my code.
sig_atomic_t child_exit_status;
sig_atomic_t child_numbers = 0;
void clean_up(int signal_number, siginfo_t * info, void* context)
{
//printf("SIGCHILD from %d calling\n", info->si_pid);
waitpid(info->si_pid, &child_exit_status, 0);
child_numbers++;
}
int main(int argc, char **argv)
{
// SIGCHLD catcher
struct sigaction sigchld_action;
memset(&sigchld_action, 0, sizeof(sigchld_action));
sigchld_action.sa_sigaction = &clean_up;
sigchld_action.sa_flags = SA_SIGINFO;
sigaction(SIGCHLD, &sigchld_action, NULL);
int pid1, pid2, pid3, pid4;
printf("pid : %d\n", getpid());
pid1 = fork();
//child1
if(pid1 == 0)
{
printf("child1 %d, parent %d\n", getpid(), getppid());
}
else
{
pid2 = fork();
//child2
if(pid2 == 0)
{
printf("child2 %d, parent %d\n", getpid(), getppid());
}
else
{
pid3 = fork();
//child3
if(pid3 == 0)
{
printf("child3 %d, parent %d\n", getpid(), getppid());
}
else
{
pid4 = fork();
//child4
if(pid4 == 0)
{
printf("child4 %d, parent %d\n", getpid(), getppid());
}
else
{
while(child_numbers < 4)
{
}
printf("i got the signals.");
}
}
}
}
return 0;
}
I tried something new but it also doesn't work..
void clean_up(int signal_number, siginfo_t * info, void* context)
{
printf("SIGCHILD from %d calling\n", info->si_pid);
while (1)
{
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
if (pid <= 0)
{
break;
}
else
{
waitpid(pid, &status, 0);
break;
}
}
child_numbers++;
}

Why the child process will not exit normally?

Why is the following program will not work properly?
int cnt = 0;
void deal(int sig) {
++cnt;
}
int main() {
signal(SIGUSR1, deal);
pid_t child = fork();
if (child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
raise(SIGSTOP);
freopen("ab.out", "w", stdout);
printf("child : %d\n", cnt);
} else {
int app_status, app_sig, fd;
struct user_regs_struct app_reg;
struct rusage app_ruse;
waitpid(child, &app_status, 0);
printf("father: waitpid: %d\n", app_status);
while (1) {
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
wait4(child, &app_status, 0, &app_ruse);
if (WIFEXITED(app_status)) {
printf("father: child exit normally, pid - %d\n", child);
break;
}
if (WIFSIGNALED(app_status) || (WIFSTOPPED(app_status)
&& WSTOPSIG(app_status) != SIGTRAP)) {
....
break;
}
ptrace(PTRACE_GETREGS, child, NULL, &app_reg);
if (app_reg.orig_rax == SYS_open && (fd = app_reg.rax) >= 0) {
kill(child, SIGUSR1);
}
}
}
return 0;
}
When run the program, got follow result
Why did the child process exit directly after receiving the signal?
The full code can got here.
https://pastebin.ubuntu.com/p/FddVZpfGH7/

Signal handlers not working across different process groups

I am using execp under a child created using fork for which I have set new process group and have set it has foreground process group using tcsetpgrp
Here is my code for main
int main()
{
signal(SIGINT,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
pid_t pid=fork();
if(pid==-1)
{
perror("Error in forking");
}
else if(pid == 0)
{
signal(SIGTTOU, SIG_IGN);
setpgid(getpid(),getpid());
//check denotes if process needs to be run in background or not
if(!check)
{
tcsetpgrp(STDOUT_FILENO,getpgid(getpid()));
tcsetpgrp(STDIN_FILENO,getpgid(getpid()));
}
signal(SIGTSTP, tstphandler);
signal(SIGINT,inthandler);
if(strlen(token)>0)
{
execer=execlp(token,token,args,(char*)NULL);
if (execer==-1)
{
printf("Error in execution);
}
exit(0);
}
}
else
{
//processes is a data structure which contains pid of
//processes and current status :- 0 = running in background
//, 1= dead , 2 = stopped in background , -1= in foreground.
if(check)
{
processes[pid_counter].pid=pid;
processes[pid_counter].dead=0;
}
if(!check && strlen(token)>0)
{
processes[pid_counter].pid=pid;
processes[pid_counter].dead=-1;
waitpid(pid,&status,0);
tcsetpgrp(STDOUT_FILENO,globalpgid);
tcsetpgrp(STDIN_FILENO,globalpgid);
processes[pid_counter].dead=1;
}
}
}
and these are my handlers
//SIGINT handler
void inthandler(int sig)
{
printf("int handler\n");
int i;
for(i=0;i<=pid_counter;i++)
{
if(processes[i].dead==-1)
{
kill(processes[i].pid,SIGKILL);
break;
}
}
}
//SIGTSTP handler
void tstphandler(int sig)
{
int i;
for(i=0;i<=pid_counter;i++)
{
if(processes[i].dead==-1)
{
processes[i].dead=2;
kill(processes[i].pid, SIGSTOP);
break;
}
}
tcsetpgrp(STDOUT_FILENO,globalpgid);
tcsetpgrp(STDIN_FILENO,globalpgid);
}
My problem is that these signal handlers are not being called from child processes. They are being called with their default action but not with my declared handler.

Only first line gets printed from a file. Using forks and pipes

I'm trying to make this print multiple lines of a file with spaces replaced with * and everything translated to uppercase. This is supposed be done through pipes and forks. Why is it that only the first line gets printed.
void writer(int inpipe)
{
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
read(inpipe, read_msg, BUFFER_SIZE);
printf("%s\n",read_msg);
return;
}
void p2(int inpipe)
{
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
if(pipe(fd) == -1) {
perror("Pipe error");
return;
}
pid = fork();
if(pid<0) { //error
perror("Fork Failed");
return;
}
else if(pid==0) { //child
close(fd[1]);
writer(fd[0]);
close(fd[0]);
return;
}
else { //parent, p2()
read(inpipe, read_msg, BUFFER_SIZE);
int i = 0;
while (read_msg[i] != '\0') {
read_msg[i] = toupper(read_msg[i]);
i++;
}
close(fd[0]);
write(fd[1],read_msg,(unsigned long)(strlen(read_msg)+1));
close(fd[1]);
}
return;
}
void p1(int inpipe)
{
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
if(pipe(fd) == -1) {
perror("Pipe error");
return;
}
pid = fork();
if(pid<0) { //error
perror("Fork Failed");
return;
}
else if(pid==0) { //child
close(fd[1]);
p2(fd[0]);
close(fd[0]);
return;
}
else { //parent, p1()
read(inpipe, read_msg, BUFFER_SIZE);
int i = 0;
while (read_msg[i] != '\0') {
if ((read_msg[i] == ' '))
read_msg[i] = '*';
i++;
}
//printf("%s\n",read_msg);
close(fd[0]);
write(fd[1],read_msg,(unsigned long)(strlen(read_msg)+1));
close(fd[1]);
}
return;
}
int main(int argc, char **argv) {
pid_t pid;
int fd[2];
if(pipe(fd) == -1) {
perror("Pipe error");
return 1;
}
pid = fork();
if(argv[1] != NULL) {
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
char line[BUFFER_SIZE];
while (fgets(line, sizeof(line), file)){
if(pid<0) { //error
perror("Fork Failed");
return 1;
}
else if(pid==0) { //child
close(fd[1]);
p1(fd[0]);
close(fd[0]);
}
else { //parent, main(), reader
//reading from the file and put it into the pipe[1]
close(fd[0]);
write(fd[1],line,strlen(line)+1);
close(fd[1]);
}
}
}
else
printf("No file detected.\n");
return EXIT_SUCCESS;
}

Resources