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();
}
Related
//compile and link with -pthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *pthread_function( void *ptr ){
printf("Hello from the new thread, my pid is %d\n", getpid());
}
int main() {
printf("Hello from the calling process, my pid is %d\n", getpid());
pthread_t thread;
int ret;
ret = pthread_create( &thread, NULL, pthread_function, NULL);
if (ret){
printf("ERROR; return code from pthread_create() is %d\n", ret);
exit(-1);
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
When I run this program, I got this result
Hello from the calling process, my pid is 4445
Hello from the new thread, my pid is 4445
Why in this case the pid of the calling process and the new thread are the same?
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.
In my code, I want to run a Videocapture in a separate pthread continuously, while the main thread will act as a socket server to communicate to any client (or vice versa).
When the client connects to the server, the server will immediately send the latest Videocapture frame to the client and close the connection and again wait for another connection.
I am currently using OpenCV 2.3.0 in mingw32 environment.
After looking some possible solutions on StackOverflow, I tried following them, but, however may I place the OpenCV variables either locally or globally or swapping the threads i.e. keeping Videocapture thread in main thread or in the 2nd thread, the program just hangs silently at the mutex locked area of the VideoCapture thread when the client gets connected.
I suppose this is happening when the server thread starts locking the mutex after connecting to a client.
Any reasoning or possible solution will be highly appreciated. Also, I am using prebuilt OpenCV version 2.3.0 and I need the code to be cross platform. In any case, if it points to a bug, I can obviously switch to some other version.
Server code
mynet.h
#ifndef __MYNET__
#define __MYNET__
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Windows XP. */
#endif
#include <winsock2.h>
#include <Ws2tcpip.h>
#else
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> /* Needed for getaddrinfo() and freeaddrinfo() */
#include <unistd.h> /* Needed for close() */
#endif
int sockInit(void)
{
#ifdef _WIN32
WSADATA wsa_data;
return WSAStartup(MAKEWORD(1,1), &wsa_data);
#else
return 0;
#endif
}
int sockQuit(void)
{
#ifdef _WIN32
return WSACleanup();
#else
return 0;
#endif
}
/* Note: For POSIX, typedef SOCKET as an int. */
#ifndef _WIN32
typedef int SOCKET;
#else
typedef unsigned int SOCKET;
#endif
int sockClose(SOCKET sock)
{
int status = 0;
#ifdef _WIN32
status = shutdown(sock, SD_BOTH);
if (status == 0) { status = closesocket(sock); }
#else
status = shutdown(sock, SHUT_RDWR);
if (status == 0) { status = close(sock); }
#endif
return status;
}
#if(defined(_WIN32) || defined(WIN32))
#include <windows.h>
#define mysleep(x) Sleep((x))
#else
#include <unistd.h>
#define mysleep(x) usleep((x)*1000)
#endif
#endif
netserver.cpp
#define _GLIBCXX_USE_CXX11_ABI 0
#undef _GLIBCXX_DEBUG
#include "../mynet.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <pthread.h>
using namespace cv;
Mat frame(120, 160, CV_8UC3);;
pthread_mutex_t mutex;
pthread_t thread;
void *myfunc(void *threadid)
{
int n;
int listenfd = 0,connfd = 0;
struct sockaddr_in serv_addr;
unsigned char sendBuff[160*120*3];
Mat hereframe;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
printf("socket retrieve success\n");
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(listen(listenfd, 10) == -1)
{
printf("Failed to listen\n");
}
else
{
connfd = accept(listenfd, (struct sockaddr*)NULL,NULL); // accept awaiting request
if(connfd<=0) printf("Something went wrong with write()! %s\n", strerror(errno));
else
{
while(1)
{
printf("Got client...\n");
pthread_mutex_lock (&mutex);
printf("Copying data...\n");
frame.copyTo(hereframe);
pthread_mutex_unlock (&mutex);
printf("Hereframe size: %dX%d\n", hereframe.rows, hereframe.cols);
memcpy(sendBuff, hereframe.data, 120*160*3);
printf("Sending data...\n");
n = send(connfd, (char*)sendBuff, 120*160*3,0);
if(n<0) printf("Something went wrong with write()! %s\n", strerror(errno));
printf("Closing client after writing %d bytes...\n", n);
printf("Closed...\n");
mysleep(40);
printf("Restartng data...\n");
}
sockClose(connfd);
}
}
sockQuit();
pthread_exit(NULL);
}
int main(void)
{
//cvNamedWindow("Sisplay", CV_WINDOW_AUTOSIZE);
sockInit();
pthread_mutex_init(&mutex,NULL);
VideoCapture cap;
Mat hereframe1;
cap.open(0);
cap.set( CV_CAP_PROP_FRAME_WIDTH, 160 );
cap.set( CV_CAP_PROP_FRAME_HEIGHT, 120 );
if( !cap.isOpened()) printf("Fukced up\n");
int rc;
long t;
rc = pthread_create(&thread, NULL, myfunc, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
for(;;)
{
cap >> hereframe1;
// printf("Video size: %dX%d\n", hereframe1.rows, hereframe1.cols);
pthread_mutex_lock(&mutex);
hereframe1.copyTo(frame); /* hangs here*/
pthread_mutex_unlock(&mutex);
// cvtColor(frame, gray, CV_BGR2GRAY);
Scalar tempVal = mean(hereframe1);
// printf("Mean = %f\n", tempVal.val[0]);
mysleep(30);
//if(waitKey(30)=='q') break;
// std::swap(prevgray, gray);
}
char *b;
pthread_join(thread,(void**)&b);
return 0;
}
Client code
receiver.cpp
#define _GLIBCXX_USE_CXX11_ABI 0
#include "../mynet.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv;
int main(int argc, char *argv[])
{
int sockfd = 0,n = 0;
unsigned char recvBuff[120*160*3];
struct sockaddr_in serv_addr;
sockInit();
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
printf("Connected to server...\n");
Mat frame(120, 160, CV_8UC3);
int csz = 0;
cvNamedWindow("Display", CV_WINDOW_AUTOSIZE);
printf("OK here 0\n");
for(;;)
{
csz = 0;
while((n = recv(sockfd, (char*)recvBuff, sizeof(recvBuff), 0)) > 0)
{
printf("OK here 2\n");
printf("Read %d bytes...\n", n);
csz += n;
if(csz<=120*160*3)
{
memcpy(frame.data+(csz-n), recvBuff, n);
}
if(csz>= 120*160*3) break;
}
printf("OK here 3\n");
printf("Got data of size %d bytes...\n", csz);
imshow("Display", frame);
if(csz < 120*160*3)
{
printf("\n Read Error \n");
}
if(waitKey(30)=='q') break;
// std::swap(prevgray, gray);
}
sockClose(sockfd);
sockQuit();
return 0;
}
What I think is that the OpenCV 2.3.0 functions are not thread-safe. e.g. functions like Mat::clone(), Mat::copyTo, etc. (need to clarify).
So, instead of using those OpenCV functions in mutex locked regions and OpenCV variables as a whole shared in multiple threads, I am just using basic C++ functions and raw buffers.
Using OpenCV functions in mutex locked regions and OpenCV variables as a whole shared in multiple threads does not seem to be friendly at all.
So, I have made a change in the server thread as
pthread_mutex_lock (&mutex);
//printf("Copying data...\n");
memcpy(sendBuff, frame.data, 120*160*3);
//frame.copyTo(hereframe); buggy here removed
pthread_mutex_unlock (&mutex);
And now Its working as expected. Uffh! Now, I need to clean up all the mess in my code.
In fact, I will also replace the OpenCV frame variable with a simple unsigned char buffer for the sharing.
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$
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.