[Python-checkins] python/dist/src/Modules posixmodule.c, 2.329, 2.329.2.1

aimacintyre at users.sourceforge.net aimacintyre at users.sourceforge.net
Sun Dec 12 09:34:35 CET 2004


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12399

Modified Files:
      Tag: release24-maint
	posixmodule.c 
Log Message:
OS/2 specific fixes related to SF bug # 1003471.

Also revise a related function to minimise file handle/pipe leakage
and improve reliability.

Backported from -HEAD.



Index: posixmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v
retrieving revision 2.329
retrieving revision 2.329.2.1
diff -u -d -r2.329 -r2.329.2.1
--- posixmodule.c	13 Oct 2004 15:30:56 -0000	2.329
+++ posixmodule.c	12 Dec 2004 08:34:33 -0000	2.329.2.1
@@ -3248,86 +3248,85 @@
 static int
 async_system(const char *command)
 {
-    char        *p, errormsg[256], args[1024];
-    RESULTCODES  rcodes;
-    APIRET       rc;
-    char        *shell = getenv("COMSPEC");
-    if (!shell)
-        shell = "cmd";
+	char errormsg[256], args[1024];
+	RESULTCODES rcodes;
+	APIRET rc;
 
-    strcpy(args, shell);
-    p = &args[ strlen(args)+1 ];
-    strcpy(p, "/c ");
-    strcat(p, command);
-    p += strlen(p) + 1;
-    *p = '\0';
+	char *shell = getenv("COMSPEC");
+	if (!shell)
+		shell = "cmd";
 
-    rc = DosExecPgm(errormsg, sizeof(errormsg),
-                    EXEC_ASYNC, /* Execute Async w/o Wait for Results */
-                    args,
-                    NULL,       /* Inherit Parent's Environment */
-                    &rcodes, shell);
-    return rc;
+	/* avoid overflowing the argument buffer */
+	if (strlen(shell) + 3 + strlen(command) >= 1024)
+		return ERROR_NOT_ENOUGH_MEMORY
+
+	args[0] = '\0';
+	strcat(args, shell);
+	strcat(args, "/c ");
+	strcat(args, command);
+
+	/* execute asynchronously, inheriting the environment */
+	rc = DosExecPgm(errormsg,
+			sizeof(errormsg),
+			EXEC_ASYNC,
+			args,
+			NULL,
+			&rcodes,
+			shell);
+	return rc;
 }
 
 static FILE *
 popen(const char *command, const char *mode, int pipesize, int *err)
 {
-    HFILE    rhan, whan;
-    FILE    *retfd = NULL;
-    APIRET   rc = DosCreatePipe(&rhan, &whan, pipesize);
-
-    if (rc != NO_ERROR) {
-	*err = rc;
-        return NULL; /* ERROR - Unable to Create Anon Pipe */
-    }
-
-    if (strchr(mode, 'r') != NULL) { /* Treat Command as a Data Source */
-        int oldfd = dup(1);      /* Save STDOUT Handle in Another Handle */
-
-        DosEnterCritSec();      /* Stop Other Threads While Changing Handles */
-        close(1);                /* Make STDOUT Available for Reallocation */
-
-        if (dup2(whan, 1) == 0) {      /* Connect STDOUT to Pipe Write Side */
-            DosClose(whan);            /* Close Now-Unused Pipe Write Handle */
-
-            rc = async_system(command);
-        }
-
-        dup2(oldfd, 1);          /* Reconnect STDOUT to Original Handle */
-        DosExitCritSec();        /* Now Allow Other Threads to Run */
-
-        if (rc == NO_ERROR)
-            retfd = fdopen(rhan, mode); /* And Return Pipe Read Handle */
-
-        close(oldfd);            /* And Close Saved STDOUT Handle */
-        return retfd;            /* Return fd of Pipe or NULL if Error */
-
-    } else if (strchr(mode, 'w')) { /* Treat Command as a Data Sink */
-        int oldfd = dup(0);      /* Save STDIN Handle in Another Handle */
+	int oldfd, tgtfd;
+	HFILE pipeh[2];
+	APIRET rc;
 
-        DosEnterCritSec();      /* Stop Other Threads While Changing Handles */
-        close(0);                /* Make STDIN Available for Reallocation */
+	/* mode determines which of stdin or stdout is reconnected to
+	 * the pipe to the child
+	 */
+	if (strchr(mode, 'r') != NULL) {
+		tgt_fd = 1;	/* stdout */
+	} else if (strchr(mode, 'w')) {
+		tgt_fd = 0;	/* stdin */
+	} else {
+		*err = ERROR_INVALID_ACCESS;
+		return NULL;
+	}
 
-        if (dup2(rhan, 0) == 0)     { /* Connect STDIN to Pipe Read Side */
-            DosClose(rhan);           /* Close Now-Unused Pipe Read Handle */
+	/* setup the pipe
+	if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) {
+		*err = rc;
+		return NULL;
+	}
 
-            rc = async_system(command);
-        }
+	/* prevent other threads accessing stdio */
+	DosEnterCritSec();
 
-        dup2(oldfd, 0);          /* Reconnect STDIN to Original Handle */
-        DosExitCritSec();        /* Now Allow Other Threads to Run */
+	/* reconnect stdio and execute child */
+	oldfd = dup(tgtfd);
+	close(tgtfd);
+	if (dup2(pipeh[tgtfd], tgtfd) == 0) {
+		DosClose(pipeh[tgtfd]);
+		rc = async_system(command);
+	}
 
-        if (rc == NO_ERROR)
-            retfd = fdopen(whan, mode); /* And Return Pipe Write Handle */
+	/* restore stdio */
+	dup2(oldfd, tgtfd);
+	close(oldfd);
 
-        close(oldfd);            /* And Close Saved STDIN Handle */
-        return retfd;            /* Return fd of Pipe or NULL if Error */
+	/* allow other threads access to stdio */
+	DosExitCritSec();
 
-    } else {
-	*err = ERROR_INVALID_ACCESS;
-        return NULL; /* ERROR - Invalid Mode (Neither Read nor Write) */
-    }
+	/* if execution of child was successful return file stream */
+	if (rc == NO_ERROR)
+		return fdopen(pipeh[1 - tgtfd], mode);
+	else {
+		DosClose(pipeh[1 - tgtfd]);
+		*err = rc;
+		return NULL;
+	}
 }
 
 static PyObject *



More information about the Python-checkins mailing list