|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r64314 - sandbox/SOC/2010/process/boost/process
From: boris_at_[hidden]
Date: 2010-07-24 08:07:09
Author: bschaeling
Date: 2010-07-24 08:07:08 EDT (Sat, 24 Jul 2010)
New Revision: 64314
URL: http://svn.boost.org/trac/boost/changeset/64314
Log:
Added support for multithreaded applications on POSIX platforms
Text files modified:
sandbox/SOC/2010/process/boost/process/context.hpp | 10 ++-
sandbox/SOC/2010/process/boost/process/operations.hpp | 110 ++++++++++++++++++---------------------
2 files changed, 56 insertions(+), 64 deletions(-)
Modified: sandbox/SOC/2010/process/boost/process/context.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/context.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/context.hpp 2010-07-24 08:07:08 EDT (Sat, 24 Jul 2010)
@@ -109,10 +109,12 @@
* child processes. You override setup() in a user-defined context class
* which should be derived from this class.
*
- * On POSIX platforms setup() is called in the child process. On Windows
- * platforms setup() is called in the parent process. Furthermore a
- * reference to a STARTUPINFO structure is passed as a parameter on Windows
- * platforms.
+ * On POSIX platforms setup() is called in the child process. That's why in
+ * a multithreaded application only async-signal-safe functions must be
+ * called in setup().
+ *
+ * On Windows platforms setup() is called in the parent process. A
+ * reference to a STARTUPINFOA structure is passed as parameter.
*/
void setup()
{
Modified: sandbox/SOC/2010/process/boost/process/operations.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/operations.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/operations.hpp 2010-07-24 08:07:08 EDT (Sat, 24 Jul 2010)
@@ -29,10 +29,12 @@
# include <stdlib.h>
# include <unistd.h>
# if defined(__CYGWIN__)
+# include <boost/scoped_array.hpp>
# include <sys/cygwin.h>
# endif
#elif defined(BOOST_WINDOWS_API)
# include <boost/process/detail/windows_helpers.hpp>
+# include <boost/scoped_array.hpp>
# include <boost/shared_array.hpp>
# include <windows.h>
#else
@@ -46,7 +48,6 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
-#include <boost/scoped_array.hpp>
#include <boost/assert.hpp>
#include <string>
#include <vector>
@@ -187,86 +188,75 @@
args.insert(args.begin(), p_name);
#if defined(BOOST_POSIX_API)
+ // Between fork() and execve() only async-signal-safe functions
+ // must be called if multithreaded applications should be supported.
+ // That's why the following code is executed before fork() is called.
+#if defined(F_MAXFD)
+ int maxdescs = fcntl(-1, F_MAXFD, 0);
+ if (maxdescs == -1)
+ maxdescs = sysconf(_SC_OPEN_MAX);
+#else
+ int maxdescs = sysconf(_SC_OPEN_MAX);
+#endif
+ if (maxdescs == -1)
+ maxdescs = 1024;
+ std::vector<bool> closeflags(maxdescs, true);
+ std::pair<std::size_t, char**> argv = detail::collection_to_argv(args);
+ std::pair<std::size_t, char**> envp =
+ detail::environment_to_envp(ctx.environment);
+
pid_t pid = fork();
if (pid == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed");
else if (pid == 0)
{
-#if defined(F_MAXFD)
- int maxdescs = fcntl(-1, F_MAXFD, 0);
- if (maxdescs == -1)
- maxdescs = sysconf(_SC_OPEN_MAX);
-#else
- int maxdescs = sysconf(_SC_OPEN_MAX);
-#endif
- if (maxdescs == -1)
- maxdescs = 1024;
- try
+ int stdin_fd = ctx.stdin_behavior->get_child_end();
+ if (stdin_fd != -1)
{
- boost::scoped_array<bool> closeflags(new bool[maxdescs]);
- for (int i = 0; i < maxdescs; ++i)
- closeflags[i] = true;
-
- int stdin_fd = ctx.stdin_behavior->get_child_end();
- if (stdin_fd != -1)
+ if (dup2(stdin_fd, STDIN_FILENO) == -1)
{
- if (dup2(stdin_fd, STDIN_FILENO) == -1)
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("dup2() failed");
- closeflags[STDIN_FILENO] = false;
- }
-
- int stdout_fd = ctx.stdout_behavior->get_child_end();
- if (stdout_fd != -1)
- {
- if (dup2(stdout_fd, STDOUT_FILENO) == -1)
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("dup2() failed");
- closeflags[STDOUT_FILENO] = false;
+ write(STDERR_FILENO, "dup2() failed\n", 14);
+ _exit(127);
}
+ closeflags[STDIN_FILENO] = false;
+ }
- int stderr_fd = ctx.stderr_behavior->get_child_end();
- if (stderr_fd != -1)
+ int stdout_fd = ctx.stdout_behavior->get_child_end();
+ if (stdout_fd != -1)
+ {
+ if (dup2(stdout_fd, STDOUT_FILENO) == -1)
{
- if (dup2(stderr_fd, STDERR_FILENO) == -1)
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("dup2() failed");
- closeflags[STDERR_FILENO] = false;
+ write(STDERR_FILENO, "dup2() failed\n", 14);
+ _exit(127);
}
+ closeflags[STDOUT_FILENO] = false;
+ }
- for (int i = 0; i < maxdescs; ++i)
+ int stderr_fd = ctx.stderr_behavior->get_child_end();
+ if (stderr_fd != -1)
+ {
+ if (dup2(stderr_fd, STDERR_FILENO) == -1)
{
- if (closeflags[i])
- close(i);
+ write(STDERR_FILENO, "dup2() failed\n", 14);
+ _exit(127);
}
-
- ctx.setup();
+ closeflags[STDERR_FILENO] = false;
}
- catch (const boost::system::system_error &e)
+
+ for (int i = 0; i < maxdescs; ++i)
{
- write(STDERR_FILENO, e.what(), std::strlen(e.what()));
- write(STDERR_FILENO, "\n", 1);
- std::exit(127);
+ if (closeflags[i])
+ close(i);
}
- std::pair<std::size_t, char**> argv =
- detail::collection_to_argv(args);
- std::pair<std::size_t, char**> envp =
- detail::environment_to_envp(ctx.environment);
+ ctx.setup();
execve(executable.c_str(), argv.second, envp.second);
- for (std::size_t i = 0; i < argv.first; ++i)
- delete[] argv.second[i];
- delete[] argv.second;
-
- for (std::size_t i = 0; i < envp.first; ++i)
- delete[] envp.second[i];
- delete[] envp.second;
-
- boost::system::system_error e(boost::system::error_code(errno,
- boost::system::get_system_category()),
- BOOST_PROCESS_SOURCE_LOCATION "execve(2) failed");
- write(STDERR_FILENO, e.what(), std::strlen(e.what()));
- write(STDERR_FILENO, "\n", 1);
- std::exit(127);
+ // Actually we should delete argv and envp data. As we must not
+ // call any non-async-signal-safe functions though we simply exit.
+ write(STDERR_FILENO, "execve() failed\n", 16);
+ _exit(127);
}
else
{
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk