|
From: Andy H. <And...@au...> - 2004-08-26 17:03:50
|
I'm having problems with with signals and condition wait in 2.1.2.
I have a condition variable that I use to block the main thread until
the user hits control-c, or kill the process etc. It works fine outside
valgrind, but fails wake up the main thread under valgrind. The code
looks something like:
Mutex mainMutex;
Condition mainCond;
sigHandler(int sig... )
{
if( mutex->try_lock() ) {
prinf("Signalling main thread\n");
mainCond->signal();
mainMutex->unlock();
}
}
main()
{
mainMutex->lock();
installSigHandler()
start some threads....
mainCond->wait( mainMutex );
do some cleanup and exit
}
Mutex and Condition are just c++ wrappers around posix functions.
Under valgrind, I see the "Signalling main thread" from my signal
handler, but the main thread never wakes up. Any ideas?
Thanks,
Andy
|
|
From: Paul P. <pa...@pa...> - 2004-08-26 18:11:17
|
>>>>> On Thu, 26 Aug 2004 12:02:21 -0500, Andy Howell <And...@au...> said:
> sigHandler(int sig... )
> {
> if( mutex->try_lock() ) {
> prinf("Signalling main thread\n");
> mainCond-> signal();
> mainMutex-> unlock();
> }
> }
[...]
> Mutex and Condition are just c++ wrappers around posix functions.
You can not legally call printf, or any of the pthread_* functions
from a signal handler. Your program is badly broken and exhibits
undefined behaviour :-(
Cheers,
--
Paul Pluzhnikov pa...@pa...
|
|
From: Andy H. <And...@au...> - 2004-08-26 19:44:14
|
Paul Pluzhnikov wrote:
>>>>>>On Thu, 26 Aug 2004 12:02:21 -0500, Andy Howell
<And...@au...> said:
>
>
> > sigHandler(int sig... )
> > {
> > if( mutex->try_lock() ) {
> > prinf("Signalling main thread\n");
> > mainCond-> signal();
> > mainMutex-> unlock();
> > }
> > }
> [...]
> > Mutex and Condition are just c++ wrappers around posix functions.
>
> You can not legally call printf, or any of the pthread_* functions
> from a signal handler. Your program is badly broken and exhibits
> undefined behaviour :-(
>
The printf is not in my real code. I just put it there to see if I was
getting the lock or not.
Can you suggest how I can "un-break" my code? It looks like my only
option would be open a pipe before hand and do a blocking read from it
in my main thread. In the signal handler I would just write 1 byte to
the pipe. Seems like that should be legal.
Thanks,
Andy
|
|
From: Nicholas N. <nj...@ca...> - 2004-08-27 16:09:29
|
On Thu, 26 Aug 2004, Andy Howell wrote:
>> You can not legally call printf, or any of the pthread_* functions
>> from a signal handler. Your program is badly broken and exhibits
>> undefined behaviour :-(
>
> The printf is not in my real code. I just put it there to see if I was
> getting the lock or not.
>
> Can you suggest how I can "un-break" my code? It looks like my only
> option would be open a pipe before hand and do a blocking read from it
> in my main thread. In the signal handler I would just write 1 byte to
> the pipe. Seems like that should be legal.
You can only safely call re-entrant functions from signal handlers,
although lots of software breaks this rule.
I attach below a list of commonly-used functions that are definitely
re-entrant and definitely not re-entrant.
N
NOT re-entrant:
"_IO_printf", "_IO_puts",
"syslog", "strdup",
"__libc_malloc", "__libc_calloc", "__libc_realloc", "__libc_free",
"inet_ntoa", "gethostbyname", "gethostbyaddr", "getservbynam",
"readdir", "__readdir", "__readdir64", "strtok",
"ttyname", "getttyname", "getlogin", "cuserid",
"getpwent", "getpwnam", "getpwuid",
"getgrent", "getgrnam", "getgrgid",
"asctime", "ctime", "gmtime", "localtime",
"fclose", "fflush", "fflush_unlocked", "fopen", "freopen",
"fdopen", "fopencookie", "fmemopen", "open_memstream",
"fprintf", "vfprintf", "fscanf", "vfscanf", "fgetc", "getc",
"getc_unlocked", "fgetc_unlocked", "fputc", "putc", "fputc_unlocked",
"putc_unlocked", "getw", "putw", "fgets", "fputs", "ungetc", "fseek",
"rewind",
"__pthread_mutex_lock", "__pthread_mutex_unlock",
"__pthread_mutex_trylock",
"gethostent",
"getnetent", "getnetbyname", "getnetbyaddr",
"getservent", "getservbyport",
"getprotoent", "getprotobyname", "getprotobynumber",
"getrpcent", "getrpcbyname", "getrpcbynumber",
"getmntent",
"fgetpwent", "fgetgrent",
"tmpnam",
"random", "srandom", "initstate", "setstate",
"drand48", "erand48", "lrand48", "nrand48", "mrand48", "jrand48",
"srand48", "seed48", "lcong48",
"ecvt", "fcvt", "qecvt", "qfcvt",
"strerror",
"crypt",
"setkey", "encrypt",
"hcreate", "hsearch", "hdestroy",
"ether_ntoa", "ether_aton",
"gethostbyname2", "getservbyname",
"rand", "srand",
"getdate", "getutent", "getutid", "getutline", "pututline",
// not sure about these
"nis_leaf_of", "nis_name_of", "nis_domain_of", "nis_sperror",
"getaliasent", "getaliasbyname",
"getnetgrent",
"getspent", "getspnam", "sgetspent", "fgetspent",
"ptsname ",
"BIO_gethostbyname",
re-entrant:
"_exit", "abort"/*+*/, "access", "alarm",
"cfgetispeed", "cfgetospeed", "cfsetispeed", "cfsetospeed",
"chdir", "chmod", "chown", "close", "creat", "dup", "dup2", "execle",
"execve", "exit"/*+*/, "fcntl", "fork", "fstat",
"getegid", "geteuid", "getgid", "getgroups", "getpgrp", "getpid",
"getppid", "getuid",
"kill", "link", "longjmp"/*+*/, "lseek", "mkdir", "mkfifo", "open",
"pathconf", "pause", "pipe", "read", "rename", "rmdir",
"setgid", "setpgid", "setsid", "setuid",
"__sigaction", "__libc_sigaction",
"sigaddset", "sigdelset", "sigemptyset", "sigfillset",
"sigismember", "signal"/*+*/, "sigpending",
"__sigprocmask",
"sigsuspend",
"sleep", "stat", "sysconf",
"tcdrain", "tcflow", "tcflush", "tcgetattr", "tcgetpgrp", "tcsendbreak",
"tcsetattr", "tcsetpgrp", "time", "times", "umask", "uname", "unlink",
"utime", "wait", "waitpid", "write",
"sem_post",
|
|
From: Andy H. <And...@au...> - 2004-08-27 19:53:12
|
Nicholas Nethercote wrote: > You can only safely call re-entrant functions from signal handlers, > although lots of software breaks this rule. > > I attach below a list of commonly-used functions that are definitely > re-entrant and definitely not re-entrant. > Thanks for the list. I implimented it using a pipe and a blocking read. Paul suggested I use sem_wait, which is seems to me a cleaner solution. Andy |
|
From: Tom S. <to...@pl...> - 2004-08-27 16:37:30
|
Nicholas Nethercote wrote: > On Thu, 26 Aug 2004, Andy Howell wrote: > >>> You can not legally call printf, or any of the pthread_* functions >>> from a signal handler. Your program is badly broken and exhibits >>> undefined behaviour :-( >> >> >> The printf is not in my real code. I just put it there to see if I was >> getting the lock or not. >> >> Can you suggest how I can "un-break" my code? It looks like my only >> option would be open a pipe before hand and do a blocking read from it >> in my main thread. In the signal handler I would just write 1 byte to >> the pipe. Seems like that should be legal. > > > You can only safely call re-entrant functions from signal handlers, > although lots of software breaks this rule. > > I attach below a list of commonly-used functions that are definitely > re-entrant and definitely not re-entrant. > > N Could valgrind identify (and report) when a KNOWN non re-entrant function was called from a signal handler? -- Tom Schutter (mailto:to...@pl...) Platte River Associates, Inc. (http://www.platte.com) |
|
From: Nicholas N. <nj...@ca...> - 2004-08-29 12:44:02
|
On Fri, 27 Aug 2004, Tom Schutter wrote: > Could valgrind identify (and report) when a KNOWN non re-entrant function was > called from a signal handler? Yes. See my tool "Crocus" at http://www.cl.cam.ac.uk/~njn25/software.html. N |