ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Proc-FastSpawn/FastSpawn.xs
Revision: 1.4
Committed: Tue Apr 2 04:27:01 2013 UTC (11 years, 2 months ago) by root
Branch: MAIN
CVS Tags: rel-1_0, rel-0_2
Changes since 1.3: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

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