ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Proc-FastSpawn/FastSpawn.xs
Revision: 1.2
Committed: Sat Mar 30 02:44:22 2013 UTC (11 years, 2 months ago) by root
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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