ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Proc-FastSpawn/FastSpawn.xs
Revision: 1.7
Committed: Mon Jun 10 03:02:33 2013 UTC (10 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-1_2, HEAD
Changes since 1.6: +3 -3 lines
Log Message:
1.2

File Contents

# User Rev Content
1 root 1.4 /* GetProcessId is XP and up, which means in all supported versions */
2     /* but older SDK's might need this */
3 root 1.3 #define _WIN32_WINNT NTDDI_WINXP
4    
5 root 1.1 #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9     #include <stdio.h>
10    
11     #ifdef WIN32
12    
13 root 1.3 /* perl probably did this already */
14 root 1.1 #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 root 1.7 cvec = (char **)SvPVX (sv_2mortal (NEWSV (0, sizeof (char *) * (n + 1))));
52 root 1.1
53     for (i = 0; i < n; ++i)
54 root 1.7 cvec [i] = SvPVbyte_nolen (*av_fetch (av, i, 1));
55 root 1.1
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 root 1.5 ALIAS:
73     spawnp = 1
74 root 1.1 INIT:
75     {
76     #ifdef WIN32
77     if (w32_num_children >= MAXIMUM_WAIT_OBJECTS)
78     {
79     errno = EAGAIN;
80     XSRETURN_UNDEF;
81     }
82    
83     argv = sv_2mortal (newSVsv (argv));
84     PUSHMARK (SP);
85     XPUSHs (argv);
86     PUTBACK;
87     call_pv ("Proc::FastSpawn::_quote", G_VOID | G_DISCARD);
88     SPAGAIN;
89     #endif
90     }
91     CODE:
92     {
93     extern char **environ;
94     char *const *cargv = array_to_cvec (argv);
95     char *const *cenvp = SvOK (envp) ? array_to_cvec (envp) : environ;
96     intptr_t pid;
97    
98     fflush (0);
99     #ifdef WIN32
100 root 1.5 pid = (ix ? _spawnvpe : _spawnve) (_P_NOWAIT, path, cargv, cenvp);
101 root 1.1
102     if (pid == -1)
103     XSRETURN_UNDEF;
104    
105     /* do it like perl, dadadoop dadadoop */
106     w32_child_handles [w32_num_children] = (HANDLE)pid;
107 root 1.7 pid = GetProcessId ((HANDLE)pid); /* get the real pid, unfortunately, requires wxp or newer */
108 root 1.1 w32_child_pids [w32_num_children] = pid;
109     ++w32_num_children;
110     #elif USE_SPAWN
111     {
112     pid_t xpid;
113    
114 root 1.5 errno = (ix ? posix_spawnp : posix_spawn) (&xpid, path, 0, 0, cargv, cenvp);
115 root 1.1
116     if (errno)
117     XSRETURN_UNDEF;
118    
119     pid = xpid;
120     }
121     #else
122 root 1.6 pid = (ix ? fork : vfork) ();
123    
124     if (pid < 0)
125     XSRETURN_UNDEF;
126    
127     if (pid == 0)
128     {
129     if (ix)
130     {
131     environ = (char **)cenvp;
132     execvp (path, cargv);
133     }
134     else
135     execve (path, cargv, cenvp);
136    
137     _exit (127);
138     }
139 root 1.1 #endif
140    
141     RETVAL = pid;
142     }
143     OUTPUT: RETVAL
144    
145     void
146     fd_inherit (int fd, int on = 1)
147     CODE:
148     #ifdef WIN32
149     SetHandleInformation ((HANDLE)_get_osfhandle (fd), HANDLE_FLAG_INHERIT, on ? HANDLE_FLAG_INHERIT : 0);
150     #else
151     fcntl (fd, F_SETFD, on ? 0 : FD_CLOEXEC);
152     #endif
153 root 1.5