lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

The 5.2-alpha manual says that file:close() [i.e. io.close()], when called on a
file-descriptor that had been opened by io.popen(), returns the process's
exit-status; this was not the behavior on POSIX platforms: it returned the
return-value of pclose(3), which POSIX.1-2008 (as well as the Linux manpage)
documents as being the same as is returned by waitpid(2), which must be
interpreted by the macros in <sys/wait.h>.  This is corrected.

Furthermore, the single return-value doesn't adequately reflect the possible
exit statuses of a child process, which can also exit with a signal: so (per Sam
Roberts's idea) an additional return-value returns the signal-number if the
child process terminates with a signal, in which case the first return-value is
nil.  The second return-value will be nil if the child process exited rather
than terminated from a signal, and on platforms which don't support it.

 doc/manual.html |    9 ++++++++-
 src/liolib.c    |   27 +++++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/doc/manual.html b/doc/manual.html
index c154821..c0882ae 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -8795,7 +8795,14 @@ but that takes an unpredictable amount of time to happen.
 If <code>file</code> was created with <a href="#pdf-io.popen"><code>io.popen</code></a>,
-a successful close returns the exit status of the process.
+a successful close returns the exit status of the process. On platforms that
+support it, if the child process terminated due to a signal, nil will be
+returned and the signal number is returned as a second return value. If the
+process exited rather than died from a signal, and on platforms which do not
+support signals, the second return-value is nil.
+Note that since popen() executes the command via a shell, the child process will
+not appear to have terminated due to signal unless it was executed via "exec",
+or if the shell itself died due to signal.
diff --git a/src/liolib.c b/src/liolib.c
index 658601a..b1fc70b 100644
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -18,6 +18,11 @@
 #include "lauxlib.h"
 #include "lualib.h"
+#if defined(LUA_USE_POSIX)
+    #include <sys/wait.h>
 #define MAX_SIZE_T	(~(size_t)0)
@@ -147,8 +152,26 @@ static int io_pclose (lua_State *L) {
   if (stat == -1)  /* error? */
     return pushresult(L, 0, NULL);
   else {
-    lua_pushinteger(L, stat);
-    return 1;  /* return status */
+    #if defined(LUA_USE_POSIX)
+	/* return:
+	 *   process-exit-status or nil if signaled,
+	 *   signal-number if signaled or nil if not
+	 */
+	const int exited   = WIFEXITED  ( stat );
+	const int signaled = WIFSIGNALED( stat );
+	if ( exited ) {
+	    lua_pushinteger( L, WEXITSTATUS(stat) );
+	    return 1;
+	}
+	else {
+	    lua_pushnil(L);
+	    lua_pushinteger( L, signaled ? WTERMSIG(stat) : 0 );
+	    return 2;
+	}
+    #else
+	lua_pushinteger(L, stat);
+	return 1;  /* return status */
+    #endif