I was given an assignment to practice working with signals in Linux, the course uses C++, for reasons I wont get into. The goal of the program is to fork 3 processes that each run a separate program (in my case, the separate program runs a countdown loop). The secondary program is then started when it receives a signal from the first, via a kill call for SIGUSR1, and is stopped when it receives SIGUSR2. The secondary program is also meant to receive SIGINT and SIGTSTP, output "discarded" and continue.
The problem occurs when a user tries to use SIGINT or SIGTSTP to interrupt the program while running. It catches the signal, and displays "DISCARDED"...and then gives me a new terminal prompt, then continues running, and then fails to respond to ctrl-c signals or any signal after that (after shortening the timer down, it appears to not even retrieve signals from the parent anymore past that).
and so I'm confused, because my code was implemented almost 1:1 from what my prof's example had been, and they are just as confused as I've been.
The first program (named forker.cpp)
#include <fcntl.h>
#include <fstream>
#include <cstring>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
//Program creates 2 processes
//Then those processes call a program "countdown"
//countdown each counts from 10-0, and handles signal interrupts
using namespace std;
int signalThrower();
pid_t childProc[3];
bool isParent = true;
int main(){
cout << "Parent Start" << endl;
for (int i = 0; i < 3; i++){
childProc[i] = fork();
if (childProc[i] == 0){
//if proc is zero, then its the child process
cout << "Child[" << i << "] Process: " << getpid() << endl;
isParent = false;
execlp("./countdown", "./countdown", NULL);
cout << "nothing here" << endl;
}
}
if (isParent){
sleep(5);
signalThrower();
}
cout << "Parent - End - Reached the end of program" << endl;
return 0;
}
int signalThrower(){
int status= -1;
pid_t proc = 0;
for (int i = 0; i < 3; i++){
cout << "Signal thrown to: " << childProc[i] << endl;
kill(childProc[i], SIGUSR1);
}
sleep(5);
for(int i=0; i<3; i++){
cout << "Signal thrown to: " << childProc[i] << endl;
kill(childProc[i], SIGUSR2);
}
while(proc>=0){
proc=wait(&status);
cout << "Returned: " << proc << endl;
}
return 0;
}
The second program (named countdown.cpp)
#include <fcntl.h>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
bool sigrecv = false;
static void sig_handler(int);
int main(){
struct sigaction sigcontrol;
sigcontrol.sa_handler = sig_handler;
sigemptyset(&sigcontrol.sa_mask);
sigcontrol.sa_flags = 0;
sigaction(SIGUSR1, &sigcontrol, NULL);
sigaction(SIGUSR2, &sigcontrol, NULL);
sigaction(SIGINT, &sigcontrol, NULL);
sigaction(SIGTSTP, &sigcontrol, NULL);
cout << "COUNTDOWN ON STANDBY" << endl;
while(!sigrecv){
sleep(0.1);
}
int counter = 30;
while(sigrecv){
cout << "Proc: " << getpid() << " - count: " << counter << endl;
counter--;
sleep(1);
}
}
static void sig_handler(int sig){
switch(sig){
case SIGUSR1:
sigrecv = true;
cout << "Spinning up" << endl;
break;
case SIGINT:
sigrecv = true;
cout <<"ctrl-C discarded" << endl;
break;
case SIGTSTP:
sigrecv = true;
cout << "ctrl-Z discarded" << endl;
break;
case SIGUSR2:
sigrecv = false;
cout << "shutting down" << endl;
break;
default:
cout << "Undefined Signal" << endl;
}
}
as the program runs, it catches the SIGUSR1 startup signal, then CTRL-C is detected 3 times across each process, and then the program continues running, no longer catching any signals
Both me and my prof are stuck on this one, as are multiple other students who I've shown this same issue to. Aside from the obvious problem of outputting stuff in a signal handler, what is preventing my program from catching any signals after this point?