Reputation: 45
This is my code. As you can see it is very simple. I want the program print dots until it catches SIGPROF signal. But my program seems like it's not working. How can I fix it?
void handler(int code) {
fprintf(stdout, "signal catched");
exit(0);
}
int main() {
struct itimerval new, old;
struct sigaction newact;
sigemptyset(&newact.sa_mask);
newact.sa_flags = 0;
newact.sa_handler = handler;
sigaction(SIGPROF, &newact,NULL);
new.it_interval.tv_usec = 0;
new.it_interval.tv_sec = 0;
new.it_value.tv_usec = 0;
new.it_value.tv_sec = (long int) 3;
setitimer(ITIMER_PROF, &new, &old);
while (1)
{
fprintf(stdout, ". ");
}
return 0;
}
Upvotes: 0
Views: 588
Reputation: 16540
the following proposed code:
Note: new
is a very poor choice for a variable name due to its' being a reserved word in C++.
When posting code, always post the needed #include
statements
and now, the proposed code:
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int code)
{
(void)code; // to avoid compiler message about unused parameter
write( 1, "signal catched", sizeof( "signal catched" ) );
_exit(0); // notice the leading underscore
}
int main( void ) // use a valid signature for `main()`
{
struct itimerval new, old;
struct sigaction newact;
sigemptyset(&newact.sa_mask);
newact.sa_flags = 0;
newact.sa_handler = handler;
sigaction(SIGPROF, &newact,NULL);
new.it_interval.tv_usec = 0;
new.it_interval.tv_sec = 0;
new.it_value.tv_usec = 0;
new.it_value.tv_sec = (long int) 3;
setitimer(ITIMER_PROF, &new, &old);
while (1)
{
fprintf(stdout, ". ");
}
return 0;
}
a typical run of the code results in:
. . . . . . . . . . . . . . . . . . . . . . . . .
<several thousand characters repeating '. '>
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . signal catched
Upvotes: 0
Reputation: 1
This signal handler
void handler(int code) {
fprintf(stdout, "signal catched");
exit(0);
}
violates the standards of 7.1.4 Use of library functions, paragraph 4:
The functions in the standard library are not guaranteed to be reentrant and may modify objects with static or thread storage duration.
And as noted in footnote 188:
Thus, a signal handler cannot, in general, call standard library functions.
POSIX does allow the calling of async-signal-safe functions from within a signal handler:
Per ** 2.4.3 Signal Actions**:
... the behavior is undefined ... if the signal handler calls any function defined in this standard other than one of the functions listed in the following table.
_Exit() _exit() abort() accept() access() aio_error() aio_return() aio_suspend() alarm() bind() cfgetispeed() cfgetospeed() cfsetispeed() cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect() creat() dup() dup2() execl() execle() execv() execve() faccessat() fchdir() fchmod() fchmodat() fchown() fchownat() fcntl() fdatasync() fexecve() ffs() fork() fstat() fstatat() fsync() ftruncate() futimens() getegid() geteuid() getgid() getgroups() getpeername() getpgrp() getpid() getppid() getsockname() getsockopt() getuid() htonl() htons() kill() link() linkat() listen() longjmp() lseek() lstat() memccpy() memchr() memcmp() memcpy() memmove() memset() mkdir() mkdirat() mkfifo() mkfifoat() mknod() mknodat() ntohl() ntohs() open() openat() pause() pipe() poll() posix_trace_event() pselect() pthread_kill() pthread_self() pthread_sigmask() raise() read() readlink() readlinkat() recv() recvfrom() recvmsg() rename() renameat() rmdir() select() sem_post() send() sendmsg() sendto() setgid() setpgid() setsid() setsockopt() setuid() shutdown() sigaction() sigaddset() sigdelset() sigemptyset() sigfillset() sigismember() siglongjmp() signal() sigpause() sigpending() sigprocmask() sigqueue() sigset() sigsuspend() sleep() sockatmark() socket() socketpair() stat() stpcpy() stpncpy() strcat() strchr() strcmp() strcpy() strcspn() strlen() strncat() strncmp() strncpy() strnlen() strpbrk() strrchr() strspn() strstr() strtok_r() symlink() symlinkat() tcdrain() tcflow() tcflush() tcgetattr() tcgetpgrp() tcsendbreak() tcsetattr() tcsetpgrp() time() timer_getoverrun() timer_gettime() timer_settime() times() umask() uname() unlink() unlinkat() utime() utimensat() utimes() wait() waitpid() wcpcpy() wcpncpy() wcscat() wcschr() wcscmp() wcscpy() wcscspn() wcslen() wcsncat() wcsncmp() wcsncpy() wcsnlen() wcspbrk() wcsrchr() wcsspn() wcsstr() wcstok() wmemchr() wmemcmp() wmemcpy() wmemmove() wmemset() write()
Any function not in the above table may be unsafe with respect to signals.
(note that fork()
is broken in glibc and is not async-signal-safe on Linux)
What's likely happening is that your signal handler interrupts the fprintf()
call in this loop:
while (1)
{
fprintf(stdout, ". ");
}
And that leads to a deadlock as the fprintf()
in the main while()
loop holds a lock, so when the signal handler gets called it blocks on its call to fprintf()
waiting for the lock to come free - which it can't because the call to fprintf()
that holds the lock was interrupted by the signal.
You also can not safely call exit()
from within a signal handler.
Upvotes: 1