[m-dev.] diff: io__call_system/4

Christopher Rodd SPEIRS crs at students.cs.mu.oz.au
Sun Oct 5 00:49:10 AEST 1997


Fergus, could you please review this.

I realise that the AC_TRY_CONFIGURE  section is not the most beautiful
code, but it is reasonably clear.  I didnt just try using those macros,
because that only causes a warning, not a compiler error.  I didnt use
#if ! (...)  because autoconf didnt like the ) being on a different line
to the (.   

Chris


Changes io__call_system/4 so that it returns the exit code of the
system call or an error indication. If a signal kills the system call 
then an error is returned indicating which signal occured.

NEWS:
	Document the change to the interface of io__call_system.

configure.in:
	Added a test for sys/wait.h and added a check that we are
	able to get the return value and signal number from the
	number returned by system().

runtime/conf.h.in:
	Added a #undef HAVE_SYS_WAIT line.

library/io.m:
	Added code to get the return value/signal number from the 
	return value of system();

Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.77
diff -u -r1.77 NEWS
--- NEWS	1997/10/04 06:49:29	1.77
+++ NEWS	1997/10/04 09:09:47
@@ -69,6 +69,10 @@
   solutions and then aggregating them.  This allows you
   to print out solutions as they are found, for example.
 
+* We've changed the result produced by io__call_system/4 so that it returns 
+  the exit code of the system call. If a signal causes the system call to
+  exit, then io__call_system/4 returns an error.
+
 * We've improved the C interface.
 
   We now handle the case when `main' is defined in C rather than in Mercury
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.110
diff -u -r1.110 configure.in
--- configure.in	1997/10/02 02:53:42	1.110
+++ configure.in	1997/10/04 14:32:05
@@ -221,6 +221,11 @@
 esac
 AC_HAVE_FUNCS(sysconf getpagesize memalign mprotect sigaction setitimer strerror memmove)
 #-----------------------------------------------------------------------------#
+AC_CHECK_HEADER(sys/wait.h, HAVE_SYS_WAIT_H=1)
+if test "$HAVE_SYS_WAIT_H" = 1; then
+	AC_DEFINE(HAVE_SYS_WAIT)
+fi
+#-----------------------------------------------------------------------------#
 AC_CHECK_HEADER(sys/siginfo.h, HAVE_SYS_SIGINFO_H=1)
 if test "$HAVE_SYS_SIGINFO_H" = 1; then
 	AC_DEFINE(HAVE_SYS_SIGINFO)
@@ -876,6 +881,62 @@
 	AC_DEFINE(MR_LITTLE_ENDIAN)
 fi
 AC_SUBST(MR_LITTLE_ENDIAN)
+#-----------------------------------------------------------------------------#
+AC_MSG_CHECKING(return values of system)
+AC_CACHE_VAL(mercury_cv_normal_system_retval,
+	AC_TRY_RUN([
+	#include <stdlib.h>
+	#ifdef HAVE_SYS_WAIT
+	#include <sys/wait.h>
+	#endif
+	int main() {
+		#if defined (WIFEXITED) && defined (WEXITSTATUS) && \
+			defined (WIFSIGNALED) && defined (WTERMSIG)
+		/* 
+		** All the necessary macros for handling the return values of
+		** system() are defined, so we do not need to test the return
+		** value of system()
+		*/
+		exit(0);
+	
+		#else
+		/*
+		** Normal return values from system() are considered to be
+		** when high 8 bits of the return value give the exit
+		** status, and the low 8 bits give the signal number which
+		** killed the process.
+		*/
+			if( system("exit 0") == 0 &&
+					system("exit 42") == 42 << 8 ) {
+					/* && system("kill -9 $$") == 9 */
+				exit(0);
+			} else {
+				exit(1);
+			}
+		#endif
+	}],
+	[mercury_cv_normal_system_retval=yes],
+	[mercury_cv_normal_system_retval=no],
+	AC_TRY_COMPILE([#include <sys/wait.h>], [
+	#if defined (WIFEXITED) && defined (WEXITSTATUS) && \
+		defined (WIFSIGNALED) && defined (WTERMSIG)
+
+	#else
+	/* 
+	** As these macros are not defined the compilation must fail.
+	** Unmatched brackets should do that for us.
+	*/
+		}
+	#endif
+	], 
+	[mercury_cv_normal_system_retval=yes],
+	[mercury_cv_normal_system_retval=no]))
+)
+AC_MSG_RESULT($mercury_cv_normal_system_retval)
+if test "$mercury_cv_normal_system_retval" = no; then
+	AC_MSG_ERROR(Unable to interpret return values from system)
+	exit 1
+fi
 #-----------------------------------------------------------------------------#
 AC_MSG_CHECKING(for tempnam)
 AC_CACHE_VAL(mercury_cv_has_tempnam,
Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.140
diff -u -r1.140 io.m
--- io.m	1997/09/09 18:56:14	1.140
+++ io.m	1997/10/04 09:13:25
@@ -876,6 +876,10 @@
 %		Invokes the operating system shell with the specified
 %		Command.  Result is either `ok(ExitStatus)', if it was
 %		possible to invoke the command, or `error(ErrorCode)' if not.
+%		The ExitStatus will be 0 if the command completed
+%		successfully or the return value of the system call
+%		otherwise.  If a signal kills the system call, then Result
+%		will be an error indicating which signal occured.
 
 :- pred io__error_message(io__error, string).
 :- mode io__error_message(in, out) is det.
@@ -987,9 +991,11 @@
 
 :- pred io__call_system_code(string, int, io__state, io__state).
 :- mode io__call_system_code(in, out, di, uo) is det.
-%	io__call_system(Command, Status, IO0, IO1).
+%	io__call_system_code(Command, Status, IO0, IO1).
 %		Invokes the operating system shell with the specified
-%		Command.  Returns Status = -1 on failure.
+%		Command.  Returns Status = 127 on failure.  Otherwise
+%		returns the exit status as a positive integer, or the
+%		signal which killed the command as a negative integer.
 
 :- pred io__do_open(string, string, int, io__input_stream,
 			io__state, io__state).
@@ -1954,9 +1960,15 @@
 
 io__call_system(Command, Result) -->
 	io__call_system_code(Command, Status),
-	{ Status = -1 ->
+	{ Status = 127 ->
 		% XXX improve error message
 		Result = error("can't invoke system command")
+	; Status < 0 ->
+		Signal is - Status,
+		string__int_to_string(Signal, SignalStr),
+		string__append("system command killed by signal number ",
+			SignalStr, ErrMsg),
+		Result = error(ErrMsg)
 	;
 		Result = ok(Status)
 	}.
@@ -1994,6 +2006,10 @@
 #include <string.h>
 #include <errno.h>
 
+#ifdef HAVE_SYS_WAIT
+#include <sys/wait.h>
+#endif
+
 /*
 ** Mercury files are not quite the same as C stdio FILEs,
 ** because we keep track of a little bit more information.
@@ -2554,6 +2570,33 @@
 	io__call_system_code(Command::in, Status::out, IO0::di, IO::uo),
 "
 	Status = system(Command);
+	if ( Status == -1 || Status == 127 ) {
+		/* 
+		** Return values of 127 or -1 from system() indicate that
+		** the system call failed.  Dont return -1, as -1 indicates
+		** that the system call was killed by signal number 1. 
+		*/
+		Status = 127;
+	} else {
+		#if defined (WIFEXITED) && defined (WEXITSTATUS) && \
+			defined (WIFSIGNALED) && defined (WTERMSIG)
+		if (WIFEXITED(Status))
+			Status = WEXITSTATUS(Status);
+		else if (WIFSIGNALED(Status))
+			Status = -WTERMSIG(Status);
+		else
+			Status = 127;
+	
+		#else
+		if (Status & 0xff != 0) 
+			/* the process was killed by a signal */
+			Status = -(Status & 0xff);
+		else 
+			/* the process terminated normally */
+			Status = (Status & 0xff00) >> 8;
+	
+		#endif
+	}
 	update_io(IO0, IO);
 ").
 
Index: runtime/conf.h.in
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/conf.h.in,v
retrieving revision 1.22
diff -u -r1.22 conf.h.in
--- conf.h.in	1997/10/02 02:46:00	1.22
+++ conf.h.in	1997/10/03 01:16:28
@@ -53,6 +53,7 @@
 **	HAVE_ASM_SIGCONTEXT	we have <asm/sigcontext.h> (e.g. i386 Linux)
 **	HAVE_SYS_TIME		we have <sys/time.h>
 **	HAVE_SYS_PARAM		we have <sys/param.h>
+**	HAVE_SYS_WAIT		we have <sys/wait.h>
 */
 #undef	HAVE_SYS_SIGINFO
 #undef	HAVE_UCONTEXT
@@ -60,6 +61,7 @@
 #undef	HAVE_ASM_SIGCONTEXT
 #undef	HAVE_SYS_TIME
 #undef	HAVE_SYS_PARAM
+#undef	HAVE_SYS_WAIT
 
 /*
 ** The following macros are defined iff the corresponding function or



More information about the developers mailing list