diff --git a/modules/libcom/src/osi/os/posix/osdProcess.c b/modules/libcom/src/osi/os/posix/osdProcess.c index 56267d0b8..9f33cb10b 100644 --- a/modules/libcom/src/osi/os/posix/osdProcess.c +++ b/modules/libcom/src/osi/os/posix/osdProcess.c @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include "osiProcess.h" #include "errlog.h" @@ -61,12 +63,18 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess (const char *pProcessName, const char *pBaseExecutableName) { int status; + int fds[2]; /* [reader, writer] */ + + if(pipe(fds)) + return osiSpawnDetachedProcessFail; /* * create a duplicate process */ status = fork (); if (status < 0) { + close(fds[0]); + close(fds[1]); return osiSpawnDetachedProcessFail; } @@ -75,11 +83,29 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess * in the initiating (parent) process */ if (status) { - return osiSpawnDetachedProcessSuccess; - } + osiSpawnDetachedProcessReturn ret = osiSpawnDetachedProcessSuccess; + char buf; + ssize_t n; + close(fds[1]); - /* - * This is executed only by the new child process. + n = read(fds[0], &buf, 1); + /* Success if child exec'd without sending a '!'. + * Of course child may crash soon after, but can't + * wait around for this to happen. + */ + if(n!=0) { + ret = osiSpawnDetachedProcessFail; + } + + close(fds[0]); + return ret; + } + close(fds[0]); + (void)fcntl ( fds[1], F_SETFD, FD_CLOEXEC ); + + /* This is executed only by the new child process. + * Since we may be called from a library, we don't assume that + * all other code has set properly set FD_CLOEXEC. * Close all open files except for STDIO, so they will not * be inherited by the new program. */ @@ -89,6 +115,8 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess if (fd==STDIN_FILENO) continue; if (fd==STDOUT_FILENO) continue; if (fd==STDERR_FILENO) continue; + /* pipe to our parent will be closed automatically via FD_CLOEXEC */ + if (fd==fds[1]) continue; close (fd); } } @@ -115,6 +143,10 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess fprintf ( stderr, "**** You may need to modify your PATH environment variable.\n" ); fprintf ( stderr, "**** Unable to start \"%s\" process.\n", pProcessName); } + /* signal error to parent */ + ssize_t ret = write(fds[1], "!", 1); + (void)ret; /* not much we could do about this */ + close(fds[1]); /* Don't run our parent's atexit() handlers */ _exit ( -1 ); }