posix: osiSpawnDetachedProcess() find out if exec() errors.

Presently, success just means fork()
This commit is contained in:
Michael Davidsaver
2021-04-19 10:55:24 -07:00
parent 555e671246
commit f8e720da28
+36 -4
View File
@@ -24,7 +24,9 @@
#include <unistd.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pwd.h>
#include <fcntl.h>
#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 );
}