[m-rev.] for review: use posix_spawn() instead of system() on MT grades

Peter Wang wangp at students.csse.unimelb.edu.au
Thu Jul 12 15:39:27 AEST 2007


Estimated hours taken: 3
Branches: main

There are some problems with calling system() in multi-threaded programs on the
Linux machines I have tested parallel mmc --make on.  On glibc 2.3.x machines
there have been assertion failures while launching programs.  On a glibc 2.5.x
machine the parent process got into infinite loops.

This patch replaces system() in multithreaded grades by posix_spawn(), which
doesn't seem to suffer the same problems.

configure.in:
runtime/mercury_conf.h.in:
	Check for availability of <spawn.h>, posix_spawn() and the environ
	global variable.

library/io.m:
	Use posix_spawn() to implement io.call_system_code in multi-threaded
	C grades if available.


Index: configure.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/configure.in,v
retrieving revision 1.493
diff -u -r1.493 configure.in
--- configure.in	19 Jun 2007 03:12:46 -0000	1.493
+++ configure.in	12 Jul 2007 05:19:36 -0000
@@ -963,7 +963,7 @@
 		getpid setpgid fork execlp wait kill \
 		grantpt unlockpt ptsname tcgetattr tcsetattr ioctl \
 		access sleep opendir readdir closedir mkdir symlink readlink \
-		gettimeofday setenv putenv _putenv
+		gettimeofday setenv putenv _putenv posix_spawn
 
 #-----------------------------------------------------------------------------#
 MERCURY_CHECK_FOR_HEADERS( \
@@ -971,7 +971,7 @@
 		asm/sigcontext.h sys/param.h sys/time.h sys/times.h \
 		sys/types.h sys/stat.h fcntl.h termios.h sys/ioctl.h \
 		sys/stropts.h windows.h dirent.h getopt.h malloc.h \
-		semaphore.h pthread.h time.h)
+		semaphore.h pthread.h time.h spawn.h)
 
 if test "$MR_HAVE_GETOPT_H" = 1; then
 	GETOPT_H_AVAILABLE=yes
@@ -3983,6 +3983,30 @@
 
 #-----------------------------------------------------------------------------#
 #
+# Check for the environ global variable.
+#
+AC_MSG_CHECKING(for environ global variable)
+AC_CACHE_VAL(mercury_cv_have_environ,
+AC_TRY_LINK([
+	#include <unistd.h>
+
+	extern char **environ;
+],[
+	environ
+],[mercury_cv_have_environ=yes],[mercury_cv_have_environ=no]))
+
+#
+# figure out whether the test succeeded
+#
+if test "$mercury_cv_have_environ" = yes; then
+	AC_MSG_RESULT(yes)
+	AC_DEFINE(MR_HAVE_ENVIRON)
+else
+	AC_MSG_RESULT(no)
+fi
+
+#-----------------------------------------------------------------------------#
+#
 # Check for the WIN32 Sleep function
 #
 
Index: library/io.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.394
diff -u -r1.394 io.m
--- library/io.m	22 Jun 2007 04:42:21 -0000	1.394
+++ library/io.m	12 Jul 2007 05:26:09 -0000
@@ -9004,12 +9004,67 @@
     MR_update_io(IO0, IO);
 ").
 
+:- pragma foreign_decl("C", "
+
+#ifdef MR_HAVE_ENVIRON
+    #include <unistd.h>
+
+    /* The man page says that this should be declared by the user program. */
+    extern char **environ;
+#endif
+
+#ifdef MR_HAVE_SPAWN_H
+    #include <spawn.h>
+#endif
+").
+
 :- pragma foreign_proc("C",
     io.call_system_code(Command::in, Status::out, Msg::out,
         IO0::di, IO::uo),
     [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
         does_not_affect_liveness],
 "
+    /*
+    ** In multithreaded grades, try to use posix_spawn() instead of system().
+    ** There were problems with threads and system() on Linux/glibc, probably
+    ** because system() uses fork().
+    */
+#if defined(MR_THREAD_SAFE) && defined(MR_HAVE_POSIX_SPAWN) && \
+        defined(MR_HAVE_ENVIRON)
+
+    char    *argv[4];
+    pid_t   pid;
+    int     err;
+    int     st;
+
+    argv[0] = ""sh"";
+    argv[1] = ""-c"";
+    argv[2] = Command;
+    argv[3] = NULL;
+
+    err = posix_spawn(&pid, ""/bin/sh"", NULL, NULL, argv,
+        (char * const) environ);
+    if (err != 0) {
+        /* Spawn failed. */
+        Status = 127;
+        ML_maybe_make_err_msg(MR_TRUE, errno,
+            ""error invoking system command: "", MR_PROC_LABEL, MR_TRUE, Msg);
+    } else {
+        /* Wait for the spawned process to exit. */
+        err = waitpid(pid, &st, 0);
+        if (err == -1) {
+            Status = 127;
+            ML_maybe_make_err_msg(MR_TRUE, errno,
+                ""error invoking system command: "", MR_PROC_LABEL, MR_TRUE,
+                Msg);
+        } else {
+            Status = st;
+            Msg = MR_make_string_const("""");
+        }
+    }
+
+#else   /* !MR_THREAD_SAFE || !MR_HAVE_POSIX_SPAWN || !MR_HAVE_ENVIRON */
+
     Status = system(Command);
     if (Status == -1) {
         /*
@@ -9023,6 +9078,9 @@
     } else {
         Msg = MR_make_string_const("""");
     }
+
+#endif  /* !MR_THREAD_SAFE || !MR_HAVE_POSIX_SPAWN || !MR_HAVE_ENVIRON */
+
     MR_update_io(IO0, IO);
 ").
 
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.59
diff -u -r1.59 mercury_conf.h.in
--- runtime/mercury_conf.h.in	22 Dec 2006 08:31:18 -0000	1.59
+++ runtime/mercury_conf.h.in	12 Jul 2007 05:08:45 -0000
@@ -132,6 +132,7 @@
 **	MR_HAVE_SEMAPHORE_H	we have <semaphore.h>
 ** 	MR_HAVE_PTHREAD_H	we have <pthread.h>
 **	MR_HAVE_TIME_H		we have <time.h>
+** 	MR_HAVE_SPAWN_H		we have <spawn.h>
 */
 #undef	MR_HAVE_SYS_SIGINFO_H
 #undef	MR_HAVE_SYS_SIGNAL_H
@@ -157,6 +158,7 @@
 #undef	MR_HAVE_SEMAPHORE_H
 #undef	MR_HAVE_PTHREAD_H
 #undef	MR_HAVE_TIME_H
+#undef	MR_HAVE_SPAWN_H
 
 /*
 ** MR_HAVE_POSIX_TIMES is defined if we have the POSIX
@@ -165,6 +167,11 @@
 #undef MR_HAVE_POSIX_TIMES
 
 /*
+** MR_HAVE_ENVIRON is defined if we have the environ global variable.
+*/
+#undef MR_HAVE_ENVIRON
+
+/*
 ** The following macros are defined iff the corresponding type
 ** is available (in <stdint.h>, <inttypes.h>, or <sys/types.h>):
 **
@@ -248,6 +255,7 @@
 **	MR_HAVE_SETENV		we have the setenv() function.
 **	MR_HAVE_PUTENV		we have the putenv() function.
 **	MR_HAVE__PUTENV		we have the _putenv() function.
+**	MR_HAVE_POSIX_SPAWN	we have the posix_spawn() function.
 */
 #undef	MR_HAVE_GETPID
 #undef	MR_HAVE_SETPGID
@@ -307,6 +315,7 @@
 #undef	MR_HAVE_SETENV
 #undef	MR_HAVE_PUTENV
 #undef	MR_HAVE__PUTENV
+#undef	MR_HAVE_POSIX_SPAWN
 
 /*
 ** We use mprotect() and signals to catch stack and heap overflows.
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list