ptg10805159
928 Solutions to Selected Exercises Appendix C
that we don’t know whether any of the functions we call might unmask a signal
that we’ve blocked, thereby making it possible for the function to be reentered
through another signal handler.
12.4 On FreeBSD 8.0, the program drops core. Withgdb, we are able to see that the
program initialization calls pthread functions, which callgetenvto find the
value of the LIBPTHREAD_SPINLOOPS and LIBPTHREAD_YIELDLOOPS
environment variables. However,our thread-safe version ofgetenvcalls back
into the pthread library while it is in an intermediate, inconsistent state. In
addition, the thread initialization functions call malloc,which, in turn, call
getenvto find the value of theMALLOC_OPTIONSenvironment variable.
To get around this problem, we could make the reasonable assumption that
program start-up is single threaded, and use a flag to indicate whether the thread
initialization had been completed by our version ofgetenv.While this flag is
false, our version ofgetenvcan operate as the non-reentrant version does (and
avoid all calls to pthread functions andmalloc). Then we could provide a
separate initialization function to callpthread_once,instead of calling it from
insidegetenv.This requires that the program call our initialization function
beforecallinggetenv.This solves our problem, because this can’t be done until
the program start-up initialization completes. After the program calls our
initialization function, our version ofgetenvoperates in a thread-safe manner.
12.5 We still needforkif we want to run a program from within another program
(i.e., beforecallingexec).
12.6 FigureC.13 shows a thread-safesleepimplementation that usesselectto
delay for the specified amount of time. It is thread-safe because it doesn’t use
any unprotected global or static data and calls only other thread-safe functions.
12.7 The implementation of a condition variable most likely uses a mutex to protect
its internal structure. Because this is an implementation detail and therefore
hidden, there is no portable way for us to acquireand release the lock in the fork
handlers. Since we can’t determine the state of the internal lock in a condition
variable after callingfork, it is unsafe for us to use the condition variable in the
child process.
Chapter 13
13.1 If it callschroot,the process will not be able to open/dev/log.The solution is
for the daemon to callopenlogwith anoptionofLOG_NDELAY,beforecalling
chroot.This opens the special device file (the UNIX domain datagram socket),
yielding a descriptor that is still valid, even after a call tochroot.This scenario
is encountered in daemons, such asftpd(the File Transfer Protocol daemon),
that specifically callchrootfor security reasons but still need to callsyslogto
log error conditions.