summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-24 14:02:19 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-24 14:02:19 +0000
commitcc1c97ae3113359628493e8139aaba538bed35bb (patch)
tree070f8b5437a5add6bba73e8b2f6d2061cd890a68 /io.c
parent5be0ab591cbc71bdafe32bb1b86860da2fe7e03c (diff)
io.c: spawnv
* io.c (pipe_open): merge win32 code using spawnv(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36209 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c157
1 files changed, 62 insertions, 95 deletions
diff --git a/io.c b/io.c
index daa3aa26d3..ade1f7bcaa 100644
--- a/io.c
+++ b/io.c
@@ -5340,7 +5340,13 @@ rb_pipe(int *pipes)
return ret;
}
-#ifdef HAVE_FORK
+#ifdef _WIN32
+#define HAVE_SPAWNV 1
+#define spawnv(mode, cmd, args) rb_w32_aspawn((mode), (cmd), (args))
+#define spawn(mode, cmd) rb_w32_spawn((mode), (cmd), 0)
+#endif
+
+#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
struct popen_arg {
VALUE execarg_obj;
struct rb_execarg *eargp;
@@ -5348,7 +5354,9 @@ struct popen_arg {
int pair[2];
int write_pair[2];
};
+#endif
+#ifdef HAVE_FORK
static void
popen_redirect(struct popen_arg *p)
{
@@ -5478,12 +5486,24 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
VALUE write_port;
#if defined(HAVE_FORK)
int status;
- struct popen_arg arg;
char errmsg[80] = { '\0' };
-#elif defined(_WIN32)
- volatile VALUE argbuf;
+#endif
+#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
+ struct popen_arg arg;
+ int e = 0;
+#endif
+#if defined(HAVE_SPAWNV)
+# if defined(HAVE_SPAWNVE)
+# define DO_SPAWN(cmd, args, envp) ((args) ? \
+ spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
+ spawne(P_NOWAIT, (cmd), (envp)))
+# else
+# define DO_SPAWN(cmd, args, envp) ((args) ? \
+ spawnv(P_NOWAIT, (cmd), (args)) : \
+ spawn(P_NOWAIT, (cmd)))
+# endif
char **args = NULL;
- int pair[2], write_pair[2];
+ char **envp = NULL;
#endif
#if !defined(HAVE_FORK)
struct rb_execarg sarg, *sargp = &sarg;
@@ -5493,7 +5513,7 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
int write_fd = -1;
#if !defined(HAVE_FORK)
const char *cmd = 0;
-#if !defined(_WIN32)
+#if !defined(HAVE_SPAWNV)
int argc;
VALUE *argv;
#endif
@@ -5502,12 +5522,17 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
cmd = StringValueCStr(prog);
#endif
-#if defined(HAVE_FORK)
+#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
arg.execarg_obj = execarg_obj;
arg.eargp = eargp;
arg.modef = fmode;
arg.pair[0] = arg.pair[1] = -1;
arg.write_pair[0] = arg.write_pair[1] = -1;
+# if !defined(HAVE_FORK)
+ if (eargp && !eargp->use_shell) {
+ args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
+ }
+# endif
switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
case FMODE_READABLE|FMODE_WRITABLE:
if (rb_pipe(arg.write_pair) < 0)
@@ -5541,9 +5566,29 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
}
if (!NIL_P(execarg_obj)) {
rb_execarg_fixup(execarg_obj);
+# if defined(HAVE_FORK)
pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
+# else
+ rb_execarg_run_options(eargp, sargp, NULL, 0);
+ if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
+ while ((pid = DO_SPAWN(cmd, args, envp)) == -1) {
+ /* exec failed */
+ switch (e = errno) {
+ case EAGAIN:
+# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+# endif
+ rb_thread_sleep(1);
+ continue;
+ }
+ break;
+ }
+ if (eargp)
+ rb_execarg_run_options(sargp, NULL, NULL, 0);
+# endif
}
else {
+# if defined(HAVE_FORK)
pid = rb_fork_ruby(&status);
if (pid == 0) { /* child */
rb_thread_atfork();
@@ -5552,11 +5597,16 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
rb_io_synchronized(RFILE(orig_stderr)->fptr);
return Qnil;
}
+# else
+ rb_notimplement();
+# endif
}
/* parent */
if (pid == -1) {
- int e = errno;
+# if defined(HAVE_FORK)
+ e = errno;
+# endif
close(arg.pair[0]);
close(arg.pair[1]);
if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
@@ -5564,8 +5614,10 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
close(arg.write_pair[1]);
}
errno = e;
+# if defined(HAVE_FORK)
if (errmsg[0])
rb_sys_fail(errmsg);
+# endif
rb_sys_fail_str(prog);
}
if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
@@ -5582,92 +5634,6 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
close(arg.pair[0]);
fd = arg.pair[1];
}
-#elif defined(_WIN32)
- if (eargp && !eargp->use_shell) {
- args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
- }
- switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
- case FMODE_READABLE|FMODE_WRITABLE:
- if (rb_pipe(write_pair) < 0)
- rb_sys_fail_str(prog);
- if (rb_pipe(pair) < 0) {
- int e = errno;
- close(write_pair[0]);
- close(write_pair[1]);
- errno = e;
- rb_sys_fail_str(prog);
- }
- if (eargp) {
- rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(write_pair[0]));
- rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(pair[1]));
- }
- break;
- case FMODE_READABLE:
- if (rb_pipe(pair) < 0)
- rb_sys_fail_str(prog);
- if (eargp)
- rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(pair[1]));
- break;
- case FMODE_WRITABLE:
- if (rb_pipe(pair) < 0)
- rb_sys_fail_str(prog);
- if (eargp)
- rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(pair[0]));
- break;
- default:
- rb_sys_fail_str(prog);
- }
- if (!NIL_P(execarg_obj)) {
- rb_execarg_fixup(execarg_obj);
- rb_execarg_run_options(eargp, sargp, NULL, 0);
- }
- while ((pid = (args ?
- rb_w32_aspawn(P_NOWAIT, cmd, args) :
- rb_w32_spawn(P_NOWAIT, cmd, 0))) == -1) {
- /* exec failed */
- switch (errno) {
- case EAGAIN:
-#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- rb_thread_sleep(1);
- break;
- default:
- {
- int e = errno;
- if (eargp)
- rb_execarg_run_options(sargp, NULL, NULL, 0);
- close(pair[0]);
- close(pair[1]);
- if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
- close(write_pair[0]);
- close(write_pair[1]);
- }
- errno = e;
- rb_sys_fail_str(prog);
- }
- break;
- }
- }
-
- RB_GC_GUARD(argbuf);
-
- if (eargp)
- rb_execarg_run_options(sargp, NULL, NULL, 0);
- if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
- close(pair[1]);
- fd = pair[0];
- close(write_pair[0]);
- write_fd = write_pair[1];
- }
- else if (fmode & FMODE_READABLE) {
- close(pair[1]);
- fd = pair[0];
- }
- else {
- close(pair[0]);
- fd = pair[1];
- }
#else
if (argc) {
prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
@@ -5747,8 +5713,9 @@ pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig
#if !defined(HAVE_FORK)
rb_raise(rb_eNotImpError,
"fork() function is unimplemented on this machine");
-#endif
+#else
return pipe_open(Qnil, modestr, fmode, convconfig);
+#endif
}
execarg_obj = rb_execarg_new(argc, argv, TRUE);