[Ace-users] [ace-bugs] ACE_Process::spawn() results in undefined behavior
J.T. Conklin
jtc at acorntoolworks.com
Thu Oct 25 20:36:35 CDT 2007
ACE VERSION: 5.6.1 (subversion version 79840)
HOST MACHINE and OPERATING SYSTEM:
NetBSD orac.acorntoolworks.com 3.0_STABLE NetBSD 3.0_STABLE (ORAC) #0: Tue Feb 21 20:05:51 PST 2006 jtc at orac.acorntoolworks.com:/home/jtc/netbsd/NetBSD-3/src/sys/arch/i386/compile/ORAC i386
TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
NetBSD orac.acorntoolworks.com 3.0_STABLE NetBSD 3.0_STABLE (ORAC) #0: Tue Feb 21 20:05:51 PST 2006 jtc at orac.acorntoolworks.com:/home/jtc/netbsd/NetBSD-3/src/sys/arch/i386/compile/ORAC i386
COMPILER NAME AND VERSION (AND PATCHLEVEL):
gcc version 3.3.3 (NetBSD nb3 20040520)
THE $ACE_ROOT/ace/config.h FILE [if you use a link to a platform-
specific file, simply state which one]:
config-netbsd.h
THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE [if you
use a link to a platform-specific file, simply state which one
(unless this isn't used in this case, e.g., with Microsoft Visual
C++)]:
platform_netbsd.GNU
CONTENTS OF $ACE_ROOT/bin/MakeProjectCreator/config/default.features
(used by MPC when you generate your own makefiles):
N/A
AREA/CLASS/EXAMPLE AFFECTED:
[What example failed? What module failed to compile?]
ACE_Process
DOES THE PROBLEM AFFECT:
EXECUTION
SYNOPSIS:
ACE_Process::spawn() results in undefined behavior
DESCRIPTION:
Similar to the PRF I sent this morning, ACE_Process::spawn() invokes
async-signal-unsafe functions between fork() and exec().
This PRF is for the simplest of those cases. In the child process,
if setpgid(), setregid(), or setreuid() fails, it invokes ACE_ERROR
to note the failure(s). This will result in an async-signal-unsafe
call to printf() at the very least (I wouldn't be surprised if tens
of unsafe functions are called within a single ACE_ERROR invocation).
This can result in deadlock.
REPEAT BY:
Discovered by code inspection.
SAMPLE FIX/WORKAROUND:
The enclosed patch Adds a #if 0 around each ACE_ERROR call. A case
could be made for using #if !ACE_HAS_THREADS instead. I'm interested
in opinions over which would be preferable for the master ACE sources.
Index: Process.cpp
===================================================================
--- Process.cpp (revision 79869)
+++ Process.cpp (working copy)
@@ -353,9 +353,15 @@
if (options.getgroup () != ACE_INVALID_PID
&& ACE_OS::setpgid (0,
options.getgroup ()) < 0)
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT ("%p.\n"),
- ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
+ {
+#if 0
+ // We can't emit this log message because ACE_ERROR(), etc.
+ // will invoke async signal unsafe functions.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process::spawn: setpgid failed.")));
+#endif
+ }
# endif /* ACE_LACKS_SETPGID */
# if !defined (ACE_LACKS_SETREGID)
@@ -363,9 +369,15 @@
|| options.getegid () != (uid_t) -1)
if (ACE_OS::setregid (options.getrgid (),
options.getegid ()) == -1)
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT ("%p.\n"),
- ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
+ {
+#if 0
+ // We can't emit this log message because ACE_ERROR(), etc.
+ // will invoke async signal unsafe functions.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process::spawn: setregid failed.")));
+#endif
+ }
# endif /* ACE_LACKS_SETREGID */
# if !defined (ACE_LACKS_SETREUID)
@@ -374,9 +386,15 @@
|| options.geteuid () != (uid_t) -1)
if (ACE_OS::setreuid (options.getruid (),
options.geteuid ()) == -1)
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT ("%p.\n"),
- ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
+ {
+#if 0
+ // We can't emit this log message because ACE_ERROR(), etc.
+ // will invoke async signal unsafe functions.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("ACE_Process::spawn: setreuid failed.")));
+#endif
+ }
# endif /* ACE_LACKS_SETREUID */
this->child (ACE_OS::getppid ());
--
J.T. Conklin
More information about the Ace-users
mailing list