I'm currently using a kqueue to handle multiple Clients per Thread in a Serverprocess
so I don't want the thread to be terminated when the Signal SIGPIPE appears, i would just like to remove the according socked id from the kqueue.
So My question is: Is there a way to get the according socketid inside a Signalhandle and parse it back to the Process to remove it from the event kqueue or would i have jsut to SIG_IGN the SIGPIPE
and handle the remove by returning of -1 from send? and would it return the -1 value after a timeout time or returns send -1 instantly?
And finally, if the signal ignore is my solution: where id have to put the declaration of the
typedef void (*sig_t) (int);
sig_t
signal(int sig, sig_t func);
Would it have to be in the main function?
or in the beginning of the corresponding thread? or just as global element?
I can't think of an easy way for the signal handler to come to know the current socket being processed unless you are setting some global state each time you do a socket operation.
You can ignore SIGPIPE from main. You do not define your own handler, instead you use SIG_IGN.
signal(SIGPIPE, SIG_IGN);
Or, if you are using sigaction:
struct sigaction act;
act.sa_handler = SIG_IGN;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGPIPE, &act, NULL);
Alternatively, you can issue the MSG_NOSIGNAL flag when you call send. This will suppress the generation of SIGPIPE, and instead generate an EPIPE error (which is what would happen if you ignored SIGPIPE):
ssize_t sent = send(sock, buf, sizeof(buf), MSG_NOSIGNAL);
if (sent > 0) {
/* ... */
} else {
assert(sent < 0);
swtich (errno) {
case EPIPE:
/* ...handle sending on a closed socket */
/* ...handle other error cases */
}
}
'signal( ...' code should be in 'main'.
Related
jmp_buf functjmp;
void sigsegv_handler(int sig) {
sio_printf("Caught sigsegv!\n");
siglongjmp(functjmp, 2);
return;
}
void foo(unsigned val) {
assert(0);
sio_printf("entered!\n");
}
int main() {
struct sigaction action;
action.sa_handler = sigsegv_handler;
sigemptyset(&action.sa_mask); /* Block sigs of type being handled */
sigaddset(&action.sa_mask, SIGSEGV);
action.sa_flags = SA_RESTART; /* Restart syscalls if possible */
if (sigaction(SIGSEGV, &action, NULL) < 0) {
sio_fprintf(stderr, "handler error!\n");
}
sigset_t prev_mask;
sigprocmask(SIG_BLOCK, NULL, &prev_mask);
if (sigsetjmp(functjmp, 0) == 0) {
foo(*(unsigned *)0x8);
} {
sigprocmask(SIG_BLOCK, &prev_mask, NULL);
sio_printf("jump handled!\n");
foo(*(unsigned *)0x8);
}
sio_fprintf(stderr, "how did it come here?!\n");
}
I've been debugging this code using gdb, and I cannot figure out why the program will not handle the second SIGSEGV signal with my own handler, assuming no other signals were received or sent by the program? Any sio prefixed functions are async safe variants of the stdio counterparts.
Currently, I surmise it has to do with something I'm missing in my conception about returning from the signal handler, which longjmp doesn't do at all.
Short answer: normally not possible to resume after SIGSEGV for C program. You might get more mileage with C++.
Long Answer: See discussions in Coming back to life after Segmentation Violation
Assuming OK to take the risk of undefined behavior:
It is possible to re-enable SEGV. The core issue is that during signal handler, the code explicitly blocks the SEGV signal from being triggered (with the sigaddset). In addition, the default behavior (of signal handlers) is that during signal handling, the same signal processing will be deferred until the signal handler returns. In the OP code, the signal handler never returns (because of the siglongjmp)
Both issues can be addressed by changing the original code.
// Make sure all attributes are NULL.
struct sigaction action = {} ;
action.sa_handler = sigsegv_handler;
sigemptyset(&action.sa_mask); /* Block sigs of type being handled */
// Not Needed:: sigaddset(&action.sa_mask, SIGSEGV);
// Add SA_NODEFER to disable the deferred processing of SIGSEGV.
action.sa_flags = SA_RESTART | SA_NODEFER ; /* Restart syscalls if possible */
// rest of code here
if (sigaction(SIGSEGV, &action, NULL) < 0) {
sio_fprintf(stderr, "handler error!\n");
}
...
I have a program that needs to use one custom signal handler for SIGINT and one for SIGCHILD.
I therefore added two struct sigaction called sigchildStruct and sigintStruct, and used sigaction to define two custo signal handling functions: handleSigInt() and handleSigChild()
First of all, is this the way you are supposed to do it; needing to register two separate sigaction structs?
Second of all, i need to block SIGCHILD during part of the code execution, i only want to receive the signal at one place in the code, so i used:
sigdelset(&sigchildStruct.sa_mask,SIGCHLD);
// Catch SIGCHILD signal here
sigaddset(&sigchildStruct.sa_mask,SIGCHLD);
Is that how you would do that? More importantly: there are two sigaction structs, but do i only need to change the sa_mask on one of them, or on both? Now i only changed the sa_mask on the struct called sigchildStruct, and not on the one called sigintStruct.
The rest of the code:
void handleSigchild(int sig) {
int childPID,childExitStatus;
printf("\nSIGCHILD received\n");
while ((childPID = waitpid(-1,&childExitStatus,WNOHANG)) >0) {
if (childExitStatus==2) {printf("Background process: %d%s",childPID," terminated by SIGINT\n");}
else if (childExitStatus!=0) {printf("Background process: %d%s",childPID," unknown command\n");}
printf("Background process: %d%s\n",childPID," has exited");
}
}
void handleSigInt(int sig) {
// SIGINT will be sent to all child processes so nothing needs to be done
printf("\nSIGINT received\n");
}
int main(int argc, char ** argv) {
// Sigaction for SIGCHILD
struct sigaction sigchildStruct;
sigchildStruct.sa_handler = &handleSigchild;
sigemptyset(&sigchildStruct.sa_mask);
sigaddset(&sigchildStruct.sa_mask,SIGCHLD);
sigchildStruct.sa_flags = SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sigchildStruct, 0) == -1) {
printf("Couldnt register signal handler: %s\n",strerror(errno));
exit(1);
}
// Sigaction for SIGINT
struct sigaction sigintStruct;
sigintStruct.sa_handler = &handleSigInt;
sigemptyset(&sigintStruct.sa_mask);
sigintStruct.sa_flags = SA_RESTART;
if (sigaction(SIGINT, &sigintStruct, 0) == -1) {
printf("Couldnt register signal handler: %s\n",strerror(errno));
exit(1);
}
sigdelset(&sigchildStruct.sa_mask,SIGCHLD);
// Catch SIGCHILD signal here
sigaddset(&sigchildStruct.sa_mask,SIGCHLD);
}
Because nobody answered, I'll try to do so. When I am dealing with signals I am using the function signal. This function takes two parameters: signal code and signal handler function. To start catching the signals I would put the code:
signal(SIGINT, handleSigInt);
signal(SIGCHILD, handleSigChild);
To stop catching the signal, I would execute:
signal(SIGINT, SIG_IGN);
signal(SIGCHILD, SIG_IGN);
Hope it helps.
There is several mistakes in your code.
1) It is not necessary to add SIGCHLD signal in the set of blocked signals during its handling. Every catched signal is blocked during its handling, so that there is no concurrent reentrance in the handling function :
struct sigaction sigchildStruct;
sigchildStruct.sa_handler = &handleSigchild;
sigemptyset(&sigchildStruct.sa_mask);
// sigaddset(&sigchildStruct.sa_mask,SIGCHLD); // unnecessary
sigchildStruct.sa_flags = SA_NOCLDSTOP;
2) You modified the sa_mask value of the struct after setting the action, which has no effect. If you want to block the delivery of signals for some time you need to modify the process signal mask. There is a function to do that : sigprocmask. So you can do something like :
sigset_t oldMask, newMask;
sigemptyset(&newMask);
sigaddset(&newMask,SIGCHLD);
sigprocmask(SIG_BLOCK,&newMask,&oldMask);
// now protected from SIGCHLD delivery, signal will be blocked...
sigprocmask(SIG_SETMASK,&oldMask,NULL);
// old protection reinstalled...
I'm currently trying to break out of the wait for accept() and/or write() by using signals, in this case SIGINT. My the program doesn't leave either as expected.
void sigHandler(int signal ){
printf(" Exit\n");
//x is global
x = 1;
return;
}
My snipped from main I'm getting hung up on is mainly:
clientfd = accept( sockfd, (struct sockaddr *) &client_addr, (unsigned int *) &client_addr_len );
When I hit this and use my signal and return, I'm still stuck on this line of code, waiting for a user to connect to my socket. The x in the handler is to for the outer loop this piece of code is in.
Is there a better way to do what I'm trying to do? Also, let me know if this isn't enough information.
Thank you.
Edit:
Here is the check for the signal, which is back at the top of main. I think this is what you were asking for:
if ( signal( SIGINT, signalhandler ) == SIG_ERR ){
return( 1 );
}
If you establish the signal handler using signal, then the accept is automatically restarting. Using signal is similar to using sigaction with sa_flags set to include SA_RESTART. Instead of signal, use sigaction and make sure that the sa_flags field of the struct sigaction does not have the SA_RESTART bit set.
In other words, instead of: signal( SIGINT, signalhandler ), use:
struct sigaction a;
a.sa_handler = signalhandler;
a.sa_flags = 0;
sigemptyset( &a.sa_mask );
sigaction( SIGINT, &a, NULL );
I have a thread in an application that has a loop like this:
...
while (1)
{
checkDatabase();
checkChildren();
sleep(3);
}
...
checkDatabase() is self-explanatory; checkChildren() simply calls waitpid(-1, &status, WNOHANG) to deal with child processes that have either exited or received a signal.
The application works fairly well, but it has default signal handling. The problem is that this parent process has a number of threads (don't worry about child processes for now) and I don't have any experience with synchronous signals, let alone in a POSIX threads application. I have used signal() before but apparently it's non-portable and it doesn't do what I need anyway. I have no experience at all with sigaction methods, and I can't find good documentation on how to fill in the structs and so on.
What I need to do is to synchronously catch terminating signals like SIGINT, SIGTERM and SIGQUIT in the above loop (and I need to ignore SIGPIPE altogether so that I can catch the EPIPE error from IO methods), so it would look like this:
...
while (1)
{
checkDatabase();
checkChildren();
checkForSignals();
sleep(3);
}
...
All other threads should not have anything to do with the signal; only the thread that executes this loop should be aware of it. And, obviously, it needs to be a non-blocking check so the loop doesn't block during its first iteration. The method called if a signal is found will sort out the other threads and destroy mutexes, and all that.
Could anyone please give me a heads-up? Many thanks.
(Following the question's comments, and for completeness, this solution tries to avoid signal handlers.)
It is possible to block signals from being raised through sigprocmask() (or, rather, pthread_sigmask() since you're using threads). From there on, the signals that were raised but blocked are available through sigpending().
Therefore, you could do something like (error checking omitted for brevity):
sigset_t blocked;
sigemptyset(&blocked);
sigaddset(&blocked, SIGINT);
sigaddset(&blocked, SIGTERM);
sigaddset(&blocked, SIGQUIT);
pthread_sigmask(SIG_BLOCK, &blocked, NULL); // Block SIGINT, SIGTERM and SIGQUIT.
signal(SIGPIPE, SIG_IGN); // Ignore SIGPIPE.
Then, later:
void checkForSignals(void)
{
sigset_t pending;
sigpending(&pending);
if (sigismember(&pending, SIGINT)) {
// Handle SIGINT...
}
if (sigismember(&pending, SIGTERM)) {
// Handle SIGTERM...
}
if (sigismember(&pending, SIGQUIT)) {
// Handle SIGQUIT...
}
}
Since sigpending() does not block, this seems to match your requirements.
Create a signal handler for SIGINT, SIGTERM and SIGQUIT, using the same function. In that signal function just set a flag that can be polled in your loop.
Something like this:
/* Global variable, will be set to non-zero if SIGINT, SIGTERM or SIGQUIT is caught */
int term_signal_set = 0;
void my_signal_handler(int)
{
term_signal_set = 1;
}
/* ... */
signal(SIGINT, my_signal_handler);
signal(SIGTERM, my_signal_handler);
signal(SIGQUIT, my_signal_handler);
signal(SIGPIPE, SIG_IGN); /* So functions return EPIPE */
while (1)
{
/* ... */
if (term_signal_set > 0)
break; /* Or do something else */
sleep(3);
}
In a multithreaded application receiving a signal, there is no predetermination, which thread receives the signal. Typical workaraounds include setting a global variable in the signal handler and checking it from a dedicated thread.
So in your case the signal handler (called from whatever thread) would just set something like a global variable for the signal received, and in CheckForSignals() you would test it.
sigaction is the way to go. man sigaction should help you. Here is an example from the web
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
struct sigaction act;
void sighandler(int signum, siginfo_t *info, void *ptr)
{
printf("Received signal %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
}
int main()
{
printf("I am %lu\n", (unsigned long)getpid());
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &act, NULL);
// Waiting for CTRL+C...
sleep(100);
return 0;
}
When I test my program using a web browser I can write to the socket/FD just fine so i decided to loop it and cut the connection mid-connection and I noticed a problem. send() is capable of closing down the entire program when the socket is unavailable. I thought the problem was that the program caught itself in a catch-22 and closed itself. So I set the socket to not block. No change. Any ideas of why this is happening?
else if ( b->temp_socket_list[read].revents & POLLOUT ) {
printf ( "#Write#\n" );
char *done = "Done!";
int sent = send ( sock, done, 5, 0 );
printf ( "end\n", sent );
}
This is likely due to the default action of the SIGPIPE signal. To ignore this signal, use something like:
signal(SIGPIPE, SIG_IGN);
Socket errors will then be reported as return values from socket functions, rather than a signal.
Which platform is this?
On UNIX in some cases you can get a signal when the connection goes down (SIGPIPE) and this terminates the program by default... the solution is to install a signal handler for SIGPIPE that does nothing.
Try this:
sigset_t set, oldset;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, &oldset);
/* use send all you like here */
sigtimedwait(&set, 0, (struct timespec [1]){0});
pthread_sigmask(SIG_SETMASK, &oldset, 0);
I'm not 100% sure it works, but I believe it should, and if it's correct then it's a solution that can be used from library code without messing up the state of the caller or other potentially-signal-using threads.
Also note that if the program (or even just the current thread) does not want to make use of SIGPIPE, you can simplify this a lot by just leaving SIGPIPE permanently blocked:
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, &oldset);