Skip to content

Commit 823b4de

Browse files
committed
Add posix_spawn support
1 parent 3b760d4 commit 823b4de

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

pp_sys.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@
5858
# endif
5959
#endif
6060

61+
/* XXX This should be removed obviously */
62+
#define HAS_POSIX_SPAWN
63+
64+
#ifdef HAS_POSIX_SPAWN
65+
#include <spawn.h>
66+
#endif
67+
6168
/* XXX Configure test needed.
6269
h_errno might not be a simple 'int', especially for multi-threaded
6370
applications, see "extern int errno in perl.h". Creating such
@@ -4406,6 +4413,67 @@ PP(pp_system)
44064413
sigset_t newset, oldset;
44074414
#endif
44084415

4416+
#ifdef HAS_POSIX_SPAWN
4417+
SV** mark = ORIGMARK;
4418+
4419+
posix_spawnattr_t attrp;
4420+
posix_spawnattr_init(&attrp);
4421+
4422+
sigemptyset(&newset);
4423+
sigaddset(&newset, SIGCHLD);
4424+
sigprocmask(SIG_BLOCK, &newset, &oldset);
4425+
posix_spawnattr_getsigmask(&attrp, &oldset);
4426+
4427+
int success;
4428+
if (sp - mark > 1) {
4429+
const char **argv, **a;
4430+
Newx(argv, sp - mark + 1, const char*);
4431+
SAVEFREEPV(argv);
4432+
a = argv;
4433+
4434+
while (++mark <= sp) {
4435+
if (*mark) {
4436+
char *arg = savepv(SvPV_nolen_const(*mark));
4437+
SAVEFREEPV(arg);
4438+
*a++ = arg;
4439+
} else
4440+
*a++ = "";
4441+
}
4442+
*a = NULL;
4443+
4444+
success = posix_spawnp(&childpid, argv[0], NULL, &attrp, (char * const *)argv, environ);
4445+
}
4446+
else if(sp - mark == 1) {
4447+
const char* argv[] = { "/bin/sh", "-c", SvPV_nolen(*sp), NULL };
4448+
success = posix_spawnp(&childpid, argv[0], NULL, &attrp, (char * const *)argv, environ);
4449+
}
4450+
else {
4451+
success = ENOEXEC;
4452+
}
4453+
SP = ORIGMARK;
4454+
if (success != 0) {
4455+
STATUS_NATIVE_CHILD_SET(255 << 8);
4456+
XPUSHi(255 << 8);
4457+
RETURN;
4458+
}
4459+
4460+
Sigsave_t ihand,qhand; /* place to save signals during system() */
4461+
rsignal_save(SIGINT, (Sighandler_t) SIG_IGN, &ihand);
4462+
rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qhand);
4463+
4464+
int status;
4465+
do {
4466+
result = wait4pid(childpid, &status, 0);
4467+
} while (result == -1 && errno == EINTR);
4468+
4469+
sigprocmask(SIG_SETMASK, &oldset, NULL);
4470+
(void)rsignal_restore(SIGINT, &ihand);
4471+
(void)rsignal_restore(SIGQUIT, &qhand);
4472+
4473+
if (result)
4474+
STATUS_NATIVE_CHILD_SET(status);
4475+
XPUSHi(STATUS_CURRENT);
4476+
#else
44094477
if (PerlProc_pipe_cloexec(pp) >= 0)
44104478
did_pipes = 1;
44114479
#ifdef __amigaos4__
@@ -4516,6 +4584,7 @@ PP(pp_system)
45164584
}
45174585
#endif /* __amigaos4__ */
45184586
PerlProc__exit(-1);
4587+
#endif /* HAS_POSIX_SPAWN */
45194588
}
45204589
#else /* ! FORK or VMS or OS/2 */
45214590
PL_statusvalue = 0;

0 commit comments

Comments
 (0)