Skip to content

Commit d39f45e

Browse files
committed
[GR-17790] Support :chdir in #spawn.
PullRequest: truffleruby/990
2 parents 428d18b + bb408b7 commit d39f45e

File tree

10 files changed

+71
-12
lines changed

10 files changed

+71
-12
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ bench/psd.rb/psd_native/ext/psd_native/*.su
3131
bench/psd.rb/psd_native/lib/psd_native/psd_native.su
3232

3333
src/main/c/*/Makefile
34+
!src/main/c/spawn-helper/Makefile
3435
!src/main/c/truffleposix/Makefile
3536
src/main/c/*/*.bc
3637
src/main/c/*/*.su
3738
src/main/c/*/extconf.h
3839
src/main/c/*/mkmf.log
3940
src/main/c/cext/ruby.o
4041
src/main/c/etc/constdefs.h
42+
src/main/c/spawn-helper/spawn-helper
4143
src/main/c/sulongmock/sulongmock.c
4244
src/main/c/sulongmock/sulongmock.o
4345
src/main/c/truffleposix/truffleposix.o

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Compatibility:
88

99
* `GC.stat` can now take an option (#1716).
1010
* `Kernel#load` with `wrap` has been implemented (#1739).
11+
* Implemented `Kernel#spawn` with `:chdir` (#1492).
1112

1213
# 19.2.0
1314

mx.truffleruby/suite.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@
268268
},
269269
"output": ".",
270270
"results": [
271+
"src/main/c/spawn-helper/spawn-helper",
271272
"src/main/c/truffleposix/<lib:truffleposix>",
272273
"src/main/c/sulongmock/sulongmock.o",
273274
"src/main/c/cext/ruby.o",
@@ -461,6 +462,9 @@
461462
"file:lib/gems/specifications/test-unit-3.2.9.gemspec",
462463
"file:lib/gems/specifications/xmlrpc-0.3.0.gemspec",
463464
],
465+
"lib/truffle/": [
466+
"dependency:org.truffleruby.cext/src/main/c/spawn-helper/spawn-helper",
467+
],
464468
"src/main/c/openssl/": [
465469
"file:src/main/c/openssl/deprecation.rb",
466470
"file:src/main/c/openssl/extconf.rb",

spec/tags/core/process/spawn_tags.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ slow:Process.spawn with a command array raises a TypeError if an element in the
7272
slow:Process.spawn redirects both STDERR and STDOUT at the time to the given name
7373
fails:Process.spawn sets the umask if given the :umask option
7474
fails:Process.spawn raises an Errno::EACCES when the file does not have execute permissions
75-
fails:Process.spawn with multiple arguments raises an ArgumentError if an argument includes a null byte
76-
fails:Process.spawn with a command array raises an ArgumentError if the Strings in the Array include a null byte
77-
fails:Process.spawn when passed :chdir changes to the directory passed for :chdir
78-
fails:Process.spawn when passed :chdir calls #to_path to convert the :chdir value
7975
ci:Process.spawn redirects STDOUT to the given file if out: String
8076
ci:Process.spawn redirects STDOUT to the given file if out: [String name, String mode]
8177
ci:Process.spawn redirects STDERR to the given file if err: String

src/main/c/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ CFLAGS := -Wall -Werror -Wno-unused-function -fPIC -std=c99
1717
LDFLAGS := -m64
1818

1919
TRUFFLE_POSIX := truffleposix/libtruffleposix.$(DLEXT)
20+
SPAWN_HELPER := spawn-helper/spawn-helper
2021
SULONG_HEADERS := $(SULONG_POLYGLOT_H)
2122
GENERATE_SULONG_MOCK := $(ROOT)/tool/generate-sulongmock.rb
2223

@@ -25,7 +26,7 @@ RBCONFIG := $(ROOT)/lib/truffle/rbconfig.rb
2526
RBCONFIG_MKMF := $(ROOT)/lib/truffle/rbconfig-for-mkmf.rb
2627
PREPROCESS := $(ROOT)/lib/cext/preprocess.rb
2728
MKMF := $(ROOT)/lib/mri/mkmf.rb
28-
BASIC_EXTCONF_DEPS := $(TRUFFLE_POSIX) $(RUBY_HEADERS) $(RBCONFIG) $(RBCONFIG_MKMF) $(PREPROCESS) $(MKMF)
29+
BASIC_EXTCONF_DEPS := $(SPAWN_HELPER) $(TRUFFLE_POSIX) $(RUBY_HEADERS) $(RBCONFIG) $(RBCONFIG_MKMF) $(PREPROCESS) $(MKMF)
2930
# These libraries are needed for try_link() in extconf.rb
3031
EXTCONF_DEPS := $(BASIC_EXTCONF_DEPS) sulongmock/sulongmock.o cext/ruby.o cext/ruby.su
3132

@@ -51,6 +52,10 @@ clean_cexts:
5152
rm -f etc/Makefile etc/*.bc etc/etc.su etc/constdefs.h
5253
rm -f rbconfig-sizeof/Makefile rbconfig-sizeof/*.bc rbconfig-sizeof/sizeof.su
5354

55+
# spawn-helper
56+
$(SPAWN_HELPER): spawn-helper/Makefile spawn-helper/spawn-helper.c
57+
cd spawn-helper && $(MAKE)
58+
5459
# truffleposix
5560
$(TRUFFLE_POSIX): truffleposix/Makefile truffleposix/truffleposix.c
5661
cd truffleposix && $(MAKE)

src/main/c/spawn-helper/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CC := cc
2+
CFLAGS := -Wall -Werror -std=c99
3+
LDFLAGS := -m64
4+
5+
spawn-helper: spawn-helper.c
6+
$(CC) $(LDFLAGS) -o $@ $<
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. This
3+
* code is released under a tri EPL/GPL/LGPL license. You can use it,
4+
* redistribute it and/or modify it under the terms of the:
5+
*
6+
* Eclipse Public License version 1.0, or
7+
* GNU General Public License version 2, or
8+
* GNU Lesser General Public License version 2.1.
9+
*/
10+
11+
#include <stdlib.h>
12+
#include <stdio.h>
13+
#include <unistd.h>
14+
15+
int main(int argc, char* argv[]) {
16+
if (argc < 4) {
17+
fprintf(stderr, "Usage: %s working_directory executable argv0 args...\n", argv[0]);
18+
return EXIT_FAILURE;
19+
}
20+
21+
char* working_directory = argv[1];
22+
char* executable = argv[2];
23+
argv += 3;
24+
25+
int r = chdir(working_directory);
26+
if (r != 0) {
27+
perror("chdir");
28+
fprintf(stderr, "working_directory=%s\n", working_directory);
29+
return EXIT_FAILURE;
30+
}
31+
32+
execvp(executable, argv);
33+
34+
/* execvp only returns on failure */
35+
perror("execvp");
36+
fprintf(stderr, "executable=%s\n", executable);
37+
return EXIT_FAILURE;
38+
}

src/main/ruby/truffleruby/core/truffle/process_operations.rb

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,14 @@ def parse(env_or_cmd, *args)
155155
else
156156
if cmd = Truffle::Type.try_convert(command, Array, :to_ary)
157157
raise ArgumentError, 'wrong first argument' unless cmd.size == 2
158-
command = StringValue(cmd[0])
159-
name = StringValue(cmd[1])
158+
command = Truffle::Type.check_null_safe(StringValue(cmd[0]))
159+
name = Truffle::Type.check_null_safe(StringValue(cmd[1]))
160160
else
161-
name = command = StringValue(command)
161+
name = command = Truffle::Type.check_null_safe(StringValue(command))
162162
end
163163

164164
argv = [name]
165-
args.each { |arg| argv << StringValue(arg) }
165+
args.each { |arg| argv << Truffle::Type.check_null_safe(StringValue(arg)) }
166166

167167
@command = command
168168
@argv = argv
@@ -452,6 +452,7 @@ def posix_spawnp(command, args, env_array, options)
452452
redirects = []
453453
pgroup = -1
454454
fds_to_close = []
455+
chdir = nil
455456

456457
options.each_pair do |key, value|
457458
case key
@@ -479,11 +480,20 @@ def posix_spawnp(command, args, env_array, options)
479480
end
480481
end
481482
end
483+
when :chdir
484+
chdir = value
482485
else
483486
raise "Unknown spawn option: #{key}"
484487
end
485488
end
486489

490+
if chdir
491+
# Go through spawn-helper to change the working dir and then execve()
492+
spawn_helper = "#{Truffle::Boot.ruby_home}/lib/truffle/spawn-helper"
493+
args = [spawn_helper, chdir, command, *args]
494+
command = spawn_helper
495+
end
496+
487497
Truffle::POSIX.with_array_of_ints(redirects) do |redirects_ptr|
488498
Truffle::POSIX.with_array_of_strings_pointer(args) do |argv|
489499
Truffle::POSIX.with_array_of_strings_pointer(env_array) do |env|

test/mri/excludes/TestProcess.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
exclude :test_execopt_env_path, "needs investigation"
4141
exclude :test_execopts_chdir, "needs investigation"
4242
exclude :test_execopts_close_others, "needs investigation"
43-
exclude :test_execopts_open_chdir, "unknown spawn option: chdir"
44-
exclude :test_execopts_open_chdir_m17n_path, "needs investigation"
4543
exclude :test_execopts_rlimit, "unknown exec option: :rlimit_core"
4644
exclude :test_execopts_umask, "unknown spawn option: umask"
4745
exclude :test_popen_exit, "needs investigation"

test/mri/excludes/TestThreadQueue.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@
44
exclude :test_queue_with_trap, "needs investigation"
55
exclude :test_sized_queue_assign_max, "hangs"
66
exclude :test_sized_queue_initialized, "NullPointerException in SizedQueueNodes$PushNode"
7-
exclude :test_thr_kill, "Unknown spawn option: chdir"
87
exclude :test_sized_queue_one_closed_interrupt, "needs investigation"

0 commit comments

Comments
 (0)