Detecting exec(2) failing after performing fork(2)?
Maarten Litmaath
maart at nat.vu.nl
Tue Mar 5 08:15:40 AEST 1991
In article <1991Mar1.205944.13198 at crc.skl.dnd.ca>,
rosenqui at crc.skl.dnd.ca (Eric Rosenquist) writes:
>In article <shj.667793966 at dkuugin> shj at login.dkuug.dk (Stig Jacobsen) writes:
>>When my application desires to spawn off a background process,
>>I use something roughly like this:
>>
>>int spawn(char *path, ...)
>>{
>>
>> if (fork() == 0)
>> execlp(path, NULL);
>>
>>}
>>
>>This is fine if the exec..() call goes well. However, if the exec()
>>call fails, the error is not reported back to the parent. I get
>>a SIGCLD of course, but what I'd really like is that my spawn()
>>function just returns an error, if the exec() call fails. ...
>> ...
>
>It's too late once the fork() has completed. [...]
Wrong. The following example shows how it can be done.
(I used execvp() instead of execlp().)
------------------------------------------------------------
/*
* Compile with `-DNO_FCNTL' if your UNIX variant doesn't have fcntl(2).
* Compile with `-DNO_STRERROR' if it doesn't have strerror(3).
*/
#include <stdio.h>
#ifdef NO_FCNTL
#include <sys/ioctl.h>
#else
#include <fcntl.h>
#endif /* NO_FCNTL */
main(argc, argv)
int argc;
char **argv;
{
int err, spawn();
char *strerror();
if (argc == 1) {
fprintf(stderr, "Usage: %s command args\n", argv[0]);
exit(1);
}
err = spawn(&argv[1]);
switch (err) {
case -1:
perror("pipe");
break;
case -2:
perror("fork");
break;
default:
printf("The execvp() in the child %s.\n", err == 0 ?
"succeeded" : "failed");
if (err != 0)
printf("The reason was: %s.\n", strerror(err));
}
}
int spawn(argv)
char **argv;
{
extern int errno;
int pp[2], n, err;
if (pipe(pp) < 0)
return -1;
switch (fork()) {
case -1:
return -2;
case 0:
close(pp[0]);
/* set close-on-exec flag */
#ifdef NO_FCNTL
ioctl(pp[1], FIOCLEX, (int *) 0);
#else
fcntl(pp[1], F_SETFD, 1);
#endif /* NO_FCNTL */
execvp(*argv, argv);
/* send a message indicating the failure */
write(pp[1], (char *) &errno, sizeof errno);
_exit(1);
}
close(pp[1]);
n = read(pp[0], (char *) &err, sizeof err);
close(pp[0]);
return n == 0 ? 0 : err;
}
#ifdef NO_STRERROR
char *strerror(n)
int n;
{
extern int errno, sys_nerr;
extern char *sys_errlist[];
static char buf[32];
if ((unsigned) n < sys_nerr)
return sys_errlist[n];
sprintf(buf, "Unknown error %d", n);
return buf;
}
#endif /* NO_STRERROR */
More information about the Comp.unix.programmer
mailing list