ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Proc-FastSpawn/FastSpawn.xs
Revision: 1.3
Committed: Tue Apr 2 03:53:50 2013 UTC (11 years, 2 months ago) by root
Branch: MAIN
Changes since 1.2: +4 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /* GetProcessId is XP and up */
2 #define _WIN32_WINNT NTDDI_WINXP
3
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7
8 #include <stdio.h>
9
10 #ifdef WIN32
11
12 /* perl probably did this already */
13 #include <windows.h>
14
15 #else
16
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20
21 /* openbsd seems to have a buggy vfork (what would you expect), */
22 /* while others might implement vfork as fork in older versions, which is fine */
23 #if __linux || __FreeBSD__ || __NetBSD__ || __sun
24 #define USE_VFORK 1
25 #endif
26
27 #if !USE_VFORK
28 #if _POSIX_SPAWN >= 200809L
29 #define USE_SPAWN 1
30 #include <spawn.h>
31 #else
32 #define vfork() fork()
33 #endif
34 #endif
35
36 #endif
37
38 static char *const *
39 array_to_cvec (SV *sv)
40 {
41 AV *av;
42 int n, i;
43 char **cvec;
44
45 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
46 croak ("expected a reference to an array of argument/environment strings");
47
48 av = (AV *)SvRV (sv);
49 n = av_len (av) + 1;
50 cvec = (char **)SvPVX (sv_2mortal (NEWSV (0, sizeof (char *) * n + 1)));
51
52 for (i = 0; i < n; ++i)
53 cvec [i] = SvPVbyte_nolen (*av_fetch (av, i, 11));
54
55 cvec [n] = 0;
56
57 return cvec;
58 }
59
60 MODULE = Proc::FastSpawn PACKAGE = Proc::FastSpawn
61
62 PROTOTYPES: ENABLE
63
64 BOOT:
65 #ifndef WIN32
66 cv_undef (get_cv ("Proc::FastSpawn::_quote", 0));
67 #endif
68
69 long
70 spawn (const char *path, SV *argv, SV *envp = &PL_sv_undef)
71 INIT:
72 {
73 #ifdef WIN32
74 if (w32_num_children >= MAXIMUM_WAIT_OBJECTS)
75 {
76 errno = EAGAIN;
77 XSRETURN_UNDEF;
78 }
79
80 argv = sv_2mortal (newSVsv (argv));
81 PUSHMARK (SP);
82 XPUSHs (argv);
83 PUTBACK;
84 call_pv ("Proc::FastSpawn::_quote", G_VOID | G_DISCARD);
85 SPAGAIN;
86 #endif
87 }
88 CODE:
89 {
90 extern char **environ;
91 char *const *cargv = array_to_cvec (argv);
92 char *const *cenvp = SvOK (envp) ? array_to_cvec (envp) : environ;
93 intptr_t pid;
94
95 fflush (0);
96 #ifdef WIN32
97 pid = _spawnve (_P_NOWAIT, path, cargv, cenvp);
98
99 if (pid == -1)
100 XSRETURN_UNDEF;
101
102 /* do it like perl, dadadoop dadadoop */
103 w32_child_handles [w32_num_children] = (HANDLE)pid;
104 pid = GetProcessId ((HANDLE)pid); /* get the real pid, unfortunately, requires wxp or newer */
105 w32_child_pids [w32_num_children] = pid;
106 ++w32_num_children;
107 #elif USE_SPAWN
108 {
109 pid_t xpid;
110
111 errno = posix_spawn (&xpid, path, 0, 0, cargv, cenvp);
112
113 if (errno)
114 XSRETURN_UNDEF;
115
116 pid = xpid;
117 }
118 #else
119 pid = vfork ();
120
121 if (pid < 0)
122 XSRETURN_UNDEF;
123
124 if (pid == 0)
125 {
126 execve (path, cargv, cenvp);
127 _exit (127);
128 }
129 #endif
130
131 RETVAL = pid;
132 }
133 OUTPUT: RETVAL
134
135 void
136 fd_inherit (int fd, int on = 1)
137 CODE:
138 #ifdef WIN32
139 SetHandleInformation ((HANDLE)_get_osfhandle (fd), HANDLE_FLAG_INHERIT, on ? HANDLE_FLAG_INHERIT : 0);
140 #else
141 fcntl (fd, F_SETFD, on ? 0 : FD_CLOEXEC);
142 #endif