Date: Mon, 22 Aug 2005 08:09:38 -0600 (MDT) From: "M. Warner Losh" <imp@bsdimp.com> To: deischen@freebsd.org Cc: freebsd-hackers@freebsd.org, lists@nbux.com Subject: Re: nagios and freebsd threads issue : help please ... Message-ID: <20050822.080938.95905450.imp@bsdimp.com> In-Reply-To: <Pine.GSO.4.43.0508220654550.27356-100000@sea.ntplx.net> References: <20050822.012017.22502074.imp@bsdimp.com> <Pine.GSO.4.43.0508220654550.27356-100000@sea.ntplx.net>
next in thread | previous in thread | raw e-mail | index | archive | help
So there's something in the list, I've gone through and done a call tree analysis to show the extensive and pervastive nature of the functions that nagios calls after fork. I don't know if these are all problems or not, since I don't know if some of these functions might be called before the first thread is created with pthread_create. However, any that are called after that clearly have undefined behavior. In message: <Pine.GSO.4.43.0508220654550.27356-100000@sea.ntplx.net> Daniel Eischen <deischen@freebsd.org> writes: : > So, if any of these things is an issue, and you can point to a posix : > things that says it is an issue, then I think that the problem can be : > resolved. : : You can only execute async-signal-safe functions after a fork() : from a threaded application. free(), malloc(), popen(), fgets(), : are not async-signal-safe. The list of async-signal-safe functions : are here: : : http://www.opengroup.org/onlinepubs/009695399/nframe.html This can really be found at: http://www.opengroup.org/onlinepubs/009695399/functions/chap02_04.html The following table defines a set of functions that shall be either reentrant or non-interruptible by signals and shall be async-signal-safe. Therefore applications may invoke them, without restriction, from signal-catching functions: _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, execle, execve, fchmod, fchown, fcntl, fdatasync, fork, fpathconf, fstat, fsync, ftruncate, getegid, geteuid, getgid, getgroups, getpeername, getpgrp, getpid, getppid, getsockname, getsockopt, getuid, kill, link, listen, lseek, lstat, mkdir, mkfifo, open, pathconf, pause, pipe, poll, posix_trace_event, pselect, raise, read, readlink, recv, recvfrom, recvmsg, rename, rmdir, select, sem_post, send, sendmsg, sendto, setgid, setpgid, setsid, setsockopt, setuid, shutdown, sigaction, sigaddset, sigdelset, sigemptyset, sigfillset, sigismember, sleep, signal, sigpause, sigpending, sigprocmask, sigqueue, sigset, sigsuspend, sockatmark, socket, socketpair, stat, symlink, sysconf, tcdrain, tcflow, tcflush, tcgetattr, tcgetpgrp, tcsendbreak, tcsetattr, tcsetpgrp, time, timer_getoverrun, timer_gettime, timer_settime, times, umask, uname, unlink, utime, wait, waitpid, write [[Note, I reformatted the above ]]. : The restriction on fork() is here (20th bullet down): : : http://www.opengroup.org/onlinepubs/009695399/nframe.html http://www.opengroup.org/onlinepubs/009695399/functions/fork.html # A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called. [THR] [Option Start] Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork() calls. [Option End] When the application calls fork() from a signal handler and any of the fork handlers registered by pthread_atfork() calls a function that is not asynch-signal-safe, the behavior is undefined. Later, in the informative section, we have: When a programmer is writing a multi-threaded program, the first described use of fork(), creating new threads in the same program, is provided by the pthread_create() function. The fork() function is thus used only to run new programs, and the effects of calling functions that require certain resources between the call to fork() and the call to an exec function are undefined. Note, the 'certain resources' here means non-async-signal-safe functions. This means that the following functions that nagios calls are unsafe: In set_macro_environment_var: malloc, strcpy, strcat, setenv, unsetenv, free In set_argv_macro_environment: snprintf In free_memory (only used in the USE_MEMORY_PERFORMANCE_TWEAKS): free In my_system: alarm, (in the EMBEDDEDPERL case: anything that perl can call, strncpy, printf) popen, strcpy, fgets, functions called by set_macro_environment_var, set_argv_macro_environment, free_memory In daemon_init: snprintf, getrlimit, setrlimit, sprintf and anything else that's done as part of the daemon after daemon_init (I didn't do a call graph analysis on this). write_to_logs_and_console cleanup broker_program_state write_to_logs_and_console: strlen, write_to_all_logs, write_to_console write_to_log fopen, fprintf, fclose write_to_console write_to_syslog write_to_all_logs write_to_syslog, write_to_log write_to_syslog syslog (in the DEBUG0 defined case: printf for nearly all functions)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050822.080938.95905450.imp>