Program terminates if I use scanf - c++

I am trying to implement the timer in code, All the example that I found are using while(1) or for(;;) but when I tried with using scanf my program terminates. Is it getting any value on stdin because if I use scanf two times then timer is called two time before exiting from program.
Here is my sample code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <netinet/in.h>
#include <signal.h>
#include <time.h>
#include <linux/socket.h>
#include <time.h>
#define SIGTIMER (SIGRTMAX)
#define SIG SIGUSR1
static timer_t tid;
static timer_t tid2;
void SignalHandler(int, siginfo_t*, void* );
timer_t SetTimer(int, int);
int main(int argc, char *argv[]) {
int t;
printf("SIGRTMAX %d\n", SIGRTMAX);
printf("SIGRTMIN %d\n", SIGRTMIN);
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = SignalHandler;
// set up sigaction to catch signal
if (sigaction(SIGTIMER, &sigact, NULL) == -1) {
perror("sigaction failed");
exit( EXIT_FAILURE );
}
// Establish a handler to catch CTRL+c and use it for exiting.
sigaction(SIGINT, &sigact, NULL);
tid=SetTimer(SIGTIMER, 1000);
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = SignalHandler;
// set up sigaction to catch signal
if (sigaction(SIG, &sa, NULL) == -1) {
perror("sa failed");
exit( EXIT_FAILURE );
}
// Establish a handler to catch CTRL+c and use it for exiting.
sigaction(SIGINT, &sa, NULL);
tid2=SetTimer(SIG, 1000);
// for(;;); or while(1) Working properly
scanf("%d", &t); /// Program terminates
return 0;
}
void SignalHandler(int signo, siginfo_t* info, void* context)
{
if (signo == SIGTIMER) {
printf("Command Caller has ticked\n");
}else if (signo == SIG) {
printf("Data Caller has ticked\n");
} else if (signo == SIGINT) {
timer_delete(tid);
perror("Crtl+c cached!");
exit(1); // exit if CRTL/C is issued
}
}
timer_t SetTimer(int signo, int sec)
{
static struct sigevent sigev;
static timer_t tid;
static struct itimerspec itval;
static struct itimerspec oitval;
// Create the POSIX timer to generate signo
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = signo;
sigev.sigev_value.sival_ptr = &tid;
if (timer_create(CLOCK_REALTIME, &sigev, &tid) == 0)
{
itval.it_value.tv_sec = sec / 1000;
itval.it_value.tv_nsec = (long)(sec % 1000) * (1000000L);
itval.it_interval.tv_sec = itval.it_value.tv_sec;
itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
if (timer_settime(tid, 0, &itval, &oitval) != 0)
{
perror("time_settime error!");
}
}
else
{
perror("timer_create error!");
return NULL;
}
return tid;
}
So, How can I resolve this problem ?
Any help would be Appreciated.
Thanks, Yuvi

Signal interrupts scanf. If you add perror('scanf') after scanf output will be:
SIGRTMAX 64
SIGRTMIN 34
Command Caller has ticked
Data Caller has ticked
scanf: Interrupted system call
If you replace scanf with:
do {
errno = 0;
scanf("%d", &t);
} while(errno == EINTR);
scanf will be retried when it fail with Interrupted system call.

You absolutely cannot use printf and perror in a signal handler. They are not re-entrant.
Also, it's possible that scanf will return with an error if your program receives a signal while in it. If scanf returns EOF, check errno, it will probably be EINTR.

Related

In Winsock/Win32, how to make recv() interruptible by ctrl-c without killing process?

Here's my attempt to create a wrapper around the winsock recv function in blocking mode so that a control-c can interrupt the connection without closing the process.
I get kind of stuck on how to do a "select" to detect if I have a "ctrl-C event" or a "socket recv event".
Any ideas on how to fix this code to get it working? The idea is that, first I call the CtrlC_Init routine to install the ctrl-c handler... then I replace recv with CtrlC_Recv in my tcpip program, and finally, i and press ctrl-c while tailing a file on a remote computer and it will magically stop without exiting my program....
#include <iostream>
#include <atomic>
#include <mutex>
#include <ws2tcpip.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
atomic<HANDLE> g_event_ctrlc {0};
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType);
void CtrlC_Init()
{
g_event_ctrlc = CreateEvent(NULL, FALSE, FALSE, NULL);
SetConsoleCtrlHandler(CtrlHandler, TRUE);
}
int CtrlC_Recv( SOCKET s, char* buf, int len, int flags)
{
WSAEVENT event_recv;
HANDLE handle_array[2];
int handle_count = 0;
if (g_event_ctrlc != 0) {
handle_array[handle_count] = g_event_ctrlc;
handle_count++;
}
// Create Event Receive
event_recv = WSACreateEvent();
if (event_recv == WSA_INVALID_EVENT) {
return SOCKET_ERROR;
}
WSAEventSelect(s, event_recv, FD_READ | FD_CLOSE);
handle_array[handle_count] = event_recv;
handle_count++;
DWORD rc = WaitForMultipleObjectsEx(
handle_count,
handle_array,
FALSE, INFINITE, FALSE);
// Close Event_Recv
WSAEventSelect(s, event_recv, 0);
CloseHandle(event_recv);
// Check for Error
if(rc == WAIT_FAILED) {
DWORD err = GetLastError();
cout << "ERROR" << err << "\n";
return SOCKET_ERROR;
}
// If Event Triggered
if(rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + handle_count) {
// Ctrl-C Interrupt Event
if (g_event_ctrlc != 0) {
if (handle_array[rc] == g_event_ctrlc) {
cout << "CTRL-C CloseSocket\n";
closesocket(s);
return SOCKET_ERROR;
}
}
// Received Socket
if (handle_array[rc] == event_recv) {
return recv(s, buf, len, flags);
}
}
return SOCKET_ERROR;
}
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
//NOTE: make sure console app is run from powershell.exe
// instead of being spawned by C++ IDE...
// some C++ IDEs trap Ctrl-C before it gets to console
// preventing this handler from getting triggered.
if (fdwCtrlType == CTRL_C_EVENT) {
printf("Ctrl-c\n");
if (g_event_ctrlc != 0) {
SetEvent(g_event_ctrlc);
}
return TRUE;
}
return FALSE;
}

Zombie process is not cleanup with waitpid call

I am watching the processes with htop and I see that child process stays as zombie even though I clean up with waitpid call. Any idea why this might happen?
Thank you very much!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void child_signal_handler(int signal) {
printf("Someone is stabbed me with signal %d\n", signal);
}
int main(int argc, char** argv)
{
const pid_t child = fork();
if (child == 0) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &child_signal_handler;
sigaction(SIGTERM, &sa, NULL);
printf("Child is started in busy loop\n");
while (true)
;
} else {
const int mercy_period = 3;
printf("Parent is angry and gonna kill his child in %d sec\n", mercy_period);
sleep(mercy_period);
kill(child, SIGTERM);
// clean-up zombie child process as it is terminated before we can wait on
// it
int status = 0;
while(waitpid(-1, &status, WNOHANG) > 0);
}
return EXIT_SUCCESS;
}
waitpid glibc implementation comments
If PID is (pid_t) -1, match any process. If the WNOHANG bit is set in OPTIONS, and that child
is not already dead, return (pid_t) 0.
The while loop clearly exits immediately as 0 > 0 is false.
Change the else and the signal to SIGKILL
} else {
const int mercy_period = 3;
printf("Parent is angry and gonna kill his child in %d sec\n", mercy_period);
sleep(mercy_period);
kill(child, SIGKILL);
int status = 0;
pid_t pid = waitpid(-1, &status, WNOHANG);
while(!pid) {
pid = waitpid(-1, &status, WNOHANG);
printf("%d\n", pid);
}
}
After few attempts waitpid will return the pid of the child process. A success.

Incorrect signal processing while using dlib detector

I try block some signals in the main thread, and then create a dedicated thread to fetch those signals via sigwait. After that, in the main thread I try to use dlib frontal face detector. If I comment out face detector use, then my code works fine, but with detector the program terminates by any signal. My source code (dlib 19.19):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <thread>
#include <dlib/image_processing/frontal_face_detector.h>
int main(int argc, char *argv[])
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGUSR2);
pthread_sigmask(SIG_BLOCK, &set, NULL);
auto t = std::thread([&set]() {
for (int sig = -1; sig != SIGINT; ) {
sigwait(&set, &sig);
printf("Signal handling thread got signal %d\n", sig);
}
});
//auto d = dlib::get_frontal_face_detector();
t.join();
}
Moreover, this code works fine:
void handler(int sig, siginfo_t *, void *)
{
printf("Signal %d\n", sig);
}
int main(int argc, char *argv[])
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_sigaction = handler;
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
auto d = dlib::get_frontal_face_detector();
pause();
}

poll() catch thread return value

I have a poll() loop with a small socket communication, I want to start an other program by system() or exec() and I need the the return value of the system()/exec() but I don't want to stop the main loop while the child process is running so I thought I start it in a thread but I am not sure how to set up the pollfd to catch the thread when it is done, I am using c/c++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <poll.h>
#include <iostream>
#include <string>
#include <thread>
#include <future>
#define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
int runProgram(const std::string &programName, const std::string &fileName) {
return system((programName + " " + fileName).c_str());
}
int main(int argc, char *argv[]) {
struct sockaddr_un server;
int sock;
char buf[1024];
unlink(SOCKET_NAME);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1){
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server, 0, sizeof(struct sockaddr_un));
server.sun_family = AF_UNIX;
strncpy(server.sun_path, SOCKET_NAME, sizeof(server.sun_path) - 1);
if (bind(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(sock, 3) < -1) {
perror("listen");
exit(EXIT_FAILURE);
}
struct pollfd fds[2];
fds[0].fd = sock;
fds[0].events = POLLIN;
std::future<int> ret = std::async(&runProgram, "cat", "test.txt");
while (true) {
poll(fds, 2, -1);
if(fds[0].revents & POLLIN) {
int new_sd = accept(fds[0].fd, NULL, NULL);
if (new_sd < 0) {
perror("accept");
}
fds[1].fd = new_sd;
}
if (fds[0].revents & POLLIN) {
int rv = recv(fds[1].fd, buf, 1024, 0);
if (rv < 0)
perror("recv");
else if (rv == 0) {
printf("disconnet\n");
close(fds[1].fd);
} else {
printf("%s\n", buf);
send(fds[1].fd, buf, 1024, 0);
}
memset(buf, 0, 1024);
}
}
close(sock);
return(EXIT_SUCCESS);
}
So I want to add one more to the pollfd (fds[ret.get()]) and get a POLLIN on fds[2] when my thread is done and I can get the return value (ret.get()), here I used an exaple command cat but in my final code the command would need mach more time so I cant wait for that to finish
The simplest solution is to create an anonymous pipe (or, since you say that you are on Linux, an eventfd) and write data to one end of the pipe in the runProgram function once the call to system returns. You can then include the read end of the pipe in the set of file descriptors that you are polling.
int process_eventfd = eventfd(0, EFD_CLOEXEC);
if (process_eventfd == -1) exit(1); // change this to handle appropriately
struct pollfd fds[3];
fds[0].fd = sock;
fds[0].events = POLLIN;
fds[1].fd = process_eventfd;
fds[1].events = POLLIN;
// use fds[2] instead of fds[1] for your socket connection, etc.
You can add the eventfd number as an argument to runProgram. It should now look something like:
int runProgram(const std::string &programName, const std::string &fileName, int process_eventfd) {
return system((programName + " " + fileName).c_str());
uint64_t value = 1;
write(process_eventfd, &value, 8);
}
By the way, your current program has a bug: you always pass 2 as the number of file descriptors to poll, even before you have set up the second file descriptor in the array. You should only pass the number of valid descriptors actually present in the array.
However, if you don't need to use system and can use exec, there is no need to create another thread; just perform the following steps:
Mask (but don't ignore) the SIGCHLD signal. (You may need to set up a signal handler, even if it does nothing; I can't remember if this is true for Linux or not).
Create your external process via fork/exec
Use ppoll rather than poll, and include SIGCHLD in the signals to be enabled
If the ppoll call returns an EINTR error, use waitpid to obtain the child status
The child process will run in parallel to your program.

Is there a way to test whether pclose() will succeed?

In my C++ application, I am seeing a pclose() that hangs because the pipe's process hung and never exited. Is there anyway I could do something like select() to test whether the pclose() will return because the child process has completed? I'd rather not do a fork() instead of popen() if possible. If fork() is the only solution, are there any examples of using fork() to replace a popen() / pclose() scenario?
Probably the easiest way, particularly if you only have one child process, is to catch SIGCHLD and set a flag that the process has terminated and pclose() can be called.
Here's a simple example:
sillyprog.c:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("This is some data from the child.\n");
fflush(stdout);
sleep(5);
return 0;
}
pc.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t child_done = 0;
void handler(int signum)
{
if ( signum == SIGCHLD ) {
child_done = 1;
}
}
int main(void)
{
/* Set signal handler */
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if ( sigaction(SIGCHLD, &sa, NULL) == -1 ) {
perror("couldn't set signal handler");
return EXIT_FAILURE;
}
/* Open pipe */
FILE * fp = popen("./sillyprog", "r");
if ( !fp ) {
fprintf(stderr, "Couldn't open pipe\n");
return EXIT_FAILURE;
}
/* Get a line from pipe */
char buffer[100];
if ( !fgets(buffer, 100, fp) ) {
fprintf(stderr, "Error calling fgets()\n");
return EXIT_FAILURE;
}
const size_t len = strlen(buffer);
if ( len && buffer[len - 1] == '\n' ) {
buffer[len - 1] = 0;
}
printf("Got '%s' from pipe.\n", buffer);
/* Wait for child to finish */
while ( !child_done ) {
printf("Child not ready, waiting...\n");
sleep(1);
}
/* Close pipe */
if ( pclose(fp) == -1 ) {
fprintf(stderr, "Error calling pclose()\n");
return EXIT_FAILURE;
}
else {
printf("pclose() successfully called.\n");
}
return 0;
}
which outputs:
paul#horus:~/src/sandbox$ ./pc
Got 'This is some data from the child.' from pipe.
Child not ready, waiting...
Child not ready, waiting...
Child not ready, waiting...
Child not ready, waiting...
Child not ready, waiting...
pclose() successfully called.
paul#horus:~/src/sandbox$