summaryrefslogtreecommitdiff
path: root/process.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-05 12:59:40 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-05 12:59:40 +0000
commitad5bfed17c7cfe9728ee4726a21cd8783756cd61 (patch)
treebbac9792c34dd52a85478b8bb8b2bb7fc51ee77f /process.c
parent2073258a7d192e8d2bc853e10464a7a5fcac8f2d (diff)
downloadruby-ad5bfed17c7cfe9728ee4726a21cd8783756cd61.tar.gz
* process.c (rb_exec_arg_fixup): allocate a temporary buffer for
run_exec_dup2 here because it should be async-signal-safe. (run_exec_dup2): use the temporary buffer. (run_exec_dup2_tmpbuf_size): new function. * include/ruby/intern.h (rb_exec_arg): add dup2_tmpbuf field. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35923 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'process.c')
-rw-r--r--process.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/process.c b/process.c
index cceb67f49a..5c03157ee3 100644
--- a/process.c
+++ b/process.c
@@ -1870,13 +1870,25 @@ fill_envp_buf_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
return ST_CONTINUE;
}
+
+static long run_exec_dup2_tmpbuf_size(long n);
+
void
rb_exec_arg_fixup(struct rb_exec_arg *e)
{
VALUE unsetenv_others, envopts;
+ VALUE ary;
e->redirect_fds = check_exec_fds(e->options);
+ ary = rb_ary_entry(e->options, EXEC_OPTION_DUP2);
+ if (!NIL_P(ary)) {
+ size_t len = run_exec_dup2_tmpbuf_size(RARRAY_LEN(ary));
+ VALUE tmpbuf = hide_obj(rb_str_new(0, len));
+ rb_str_set_len(tmpbuf, len);
+ e->dup2_tmpbuf = tmpbuf;
+ }
+
unsetenv_others = rb_ary_entry(e->options, EXEC_OPTION_UNSETENV_OTHERS);
envopts = rb_ary_entry(e->options, EXEC_OPTION_ENV);
if (RTEST(unsetenv_others) || !NIL_P(envopts)) {
@@ -2110,26 +2122,30 @@ intrcmp(const void *a, const void *b)
return *(int*)b - *(int*)a;
}
+struct run_exec_dup2_fd_pair {
+ int oldfd;
+ int newfd;
+ long older_index;
+ long num_newer;
+};
+
+static long
+run_exec_dup2_tmpbuf_size(long n)
+{
+ return sizeof(struct run_exec_dup2_fd_pair) * n;
+}
+
/* This function should be async-signal-safe when _save_ is not Qnil. */
static int
-run_exec_dup2(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
+run_exec_dup2(VALUE ary, VALUE tmpbuf, VALUE save, char *errmsg, size_t errmsg_buflen)
{
long n, i;
int ret;
int extra_fd = -1;
- struct fd_pair {
- int oldfd;
- int newfd;
- long older_index;
- long num_newer;
- } *pairs = 0;
+ struct run_exec_dup2_fd_pair *pairs = 0;
n = RARRAY_LEN(ary);
- pairs = (struct fd_pair *)malloc(sizeof(struct fd_pair) * n); /* xxx: not async-signal-safe */
- if (pairs == NULL) {
- ERRMSG("malloc");
- return -1;
- }
+ pairs = (struct run_exec_dup2_fd_pair *)RSTRING_PTR(tmpbuf);
/* initialize oldfd and newfd: O(n) */
for (i = 0; i < n; i++) {
@@ -2141,16 +2157,16 @@ run_exec_dup2(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
/* sort the table by oldfd: O(n log n) */
if (!RTEST(save))
- qsort(pairs, n, sizeof(struct fd_pair), intcmp); /* hopefully async-signal-safe */
+ qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
else
- qsort(pairs, n, sizeof(struct fd_pair), intrcmp);
+ qsort(pairs, n, sizeof(struct run_exec_dup2_fd_pair), intrcmp);
/* initialize older_index and num_newer: O(n log n) */
for (i = 0; i < n; i++) {
int newfd = pairs[i].newfd;
- struct fd_pair key, *found;
+ struct run_exec_dup2_fd_pair key, *found;
key.oldfd = newfd;
- found = bsearch(&key, pairs, n, sizeof(struct fd_pair), intcmp); /* hopefully async-signal-safe */
+ found = bsearch(&key, pairs, n, sizeof(struct run_exec_dup2_fd_pair), intcmp); /* hopefully async-signal-safe */
pairs[i].num_newer = 0;
if (found) {
while (pairs < found && (found-1)->oldfd == newfd)
@@ -2245,11 +2261,9 @@ run_exec_dup2(VALUE ary, VALUE save, char *errmsg, size_t errmsg_buflen)
}
}
- free(pairs); /* xxx: not async-signal-safe */
return 0;
fail:
- free(pairs); /* xxx: not async-signal-safe */
return -1;
}
@@ -2502,7 +2516,7 @@ rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char
obj = rb_ary_entry(options, EXEC_OPTION_DUP2);
if (!NIL_P(obj)) {
- if (run_exec_dup2(obj, soptions, errmsg, errmsg_buflen) == -1) /* xxx: not async-signal-safe */
+ if (run_exec_dup2(obj, e->dup2_tmpbuf, soptions, errmsg, errmsg_buflen) == -1) /* xxx: not async-signal-safe */
return -1;
}