I'm encountering a discrepancy in the behavior of my code when using kill(pid, SIGINT) between Debian 12 and CentOS 7 in a virtual machine. Previously, this code worked as expected in Fedora 39.
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <cstdlib>
#include <cstring>
#include <sys/wait.h>
using namespace std;
void sigint_handler(int signal) {
cout << "The child process received the SIGINT signal. Ending..." << endl;
exit(EXIT_SUCCESS);
}
int main() {
pid_t pid = fork();
if (pid < 0) {
cerr << "Error creating the child process." << endl;
exit(EXIT_FAILURE);
} else if (pid == 0) {
// Child process
cout << "Child process created. PID: " << getpid() << endl;
// Signal handler for SIGINT
signal(SIGINT, sigint_handler);
// Executing ping for 10 iterations, although parent process should stop it earlier
execl("/bin/sh", "sh", "-c", "ping -c 10 google.com", NULL);
} else {
// Parent process
cout << "parent process. PID from child: " << pid << endl;
sleep(3); // Wait 3 seconds before sending the SIGINT
cout << "Sending SIGINT to the child process..." << endl;
if (kill(pid, SIGINT) == -1) {
cerr << "Error sending SIGINT to the child process." << endl;
exit(EXIT_FAILURE);
}
int status;
waitpid(pid, &status, 0); // Wait to the child process to end
if (WIFEXITED(status)) {
cout << "Child process end with status: " << WEXITSTATUS(status) << endl;
} else {
cout << "Child process end in an incorrect way" << endl;
}
}
return 0;
}
After migrating to Debian 12, the code snippet above doesn't behave as expected. Instead of stopping the ping process after sending the SIGINT signal, it continues executing all 10 iterations. However, when running the same code in a CentOS VM, it behaves correctly, stopping after a few iterations.
Why is this happening?
Thanks in advance.
Additional information:
g++ version in Debian 12: g++ (Debian 12.2.0-14) 12.2.0
g++ version in CentOS 7 VM: g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
Edit 1:
I have also tried with system("ping -c 10 google.com") instead of execl() without success. Same with sigaction() and it doesn't work.
In addition to that, the problem isn't related to the different implementations of ping in Debian and Red Hat based distros, because I have tried with my original code and it doesn't stop.
In my original code, instead of ping, I call a program.o that has a infinite loop that should be stopped with Ctrl+C. In Fedora and CentOS my program runs perfectly while in Debian it doesn't.
This does not work as it seems you expect:
execlwill reset the signal action back to the default in the new process. This is setting the signal handler tosigint_handleronly for an extremely short window.Therefore, how
pingreacts toSIGINTis completely dependent on how it sets up its signal handlers. Presumably, the different VMs have different implementations or versions ofping.iputilsandinetutilsboth have aping.