diff --git a/ChangeLog b/ChangeLog index 6143316e46..dd5192a1a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Aug 7 23:05:55 2013 Akinori MUSHA + + * ruby.c (Process.setproctitle): New method to change the title of + the running process that is shown in ps(1). [Feature #8696] + Wed Aug 7 20:05:38 2013 Tanaka Akira * bignum.c (rb_big_odd_p): Check the bignum length. diff --git a/NEWS b/NEWS index d27ad0be0b..31f4751ef7 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,10 @@ with all sufficient information, see the ChangeLog file. * misc * Mutex#owned? is no longer experimental. +* Process + * New methods: + * Process.setproctitle() sets the process title without affecting $0. + * String * New methods: * String#scrub and String#scrub! verify and fix invalid byte sequence. diff --git a/ruby.c b/ruby.c index df3f089267..6c9061ca79 100644 --- a/ruby.c +++ b/ruby.c @@ -1780,21 +1780,49 @@ rb_load_file_str(VALUE fname_v) return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt)); } +/* + * call-seq: + * Process.argv0 -> frozen_string + * + * Returns the name of the script being executed. The value is not + * affected by assigning a new value to $0. + */ + +static VALUE +proc_argv0(VALUE process) +{ + return rb_orig_progname; +} + +/* + * call-seq: + * Process.setproctitle(string) -> string + * + * Returns the process title that appears on the ps(1) command. Not + * necessarily effective on all platforms. + * + * Calling this method does not affect the value of $0. + * + * Process.setproctitle('myapp: worker #%d' % worker_id) + */ + +static VALUE +proc_setproctitle(VALUE process, VALUE title) +{ + StringValue(title); + + setproctitle("%.*s", RSTRING_LENINT(title), RSTRING_PTR(title)); + + return title; +} + static void set_arg0(VALUE val, ID id) { - char *s; - long i; - if (origarg.argv == 0) rb_raise(rb_eRuntimeError, "$0 not initialized"); - StringValue(val); - s = RSTRING_PTR(val); - i = RSTRING_LEN(val); - setproctitle("%.*s", (int)i, s); - - rb_progname = rb_obj_freeze(rb_external_str_new(s, i)); + rb_progname = rb_str_new_frozen(proc_setproctitle(rb_mProcess, val)); } /*! Sets the current script name to this value. @@ -1886,6 +1914,8 @@ ruby_prog_init(void) rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0); rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0); + rb_define_module_function(rb_mProcess, "setproctitle", proc_setproctitle, 1); + /* * ARGV contains the command line arguments used to run ruby with the * first value containing the name of the executable. diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 35422ae2ac..06c6b7337f 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -477,6 +477,25 @@ class TestRubyOptions < Test::Unit::TestCase end end + def test_setproctitle + skip "platform dependent feature" if /linux|freebsd|netbsd|openbsd|darwin/ !~ RUBY_PLATFORM + + with_tmpchdir do + write_file("test-script", "$_0 = $0.dup; Process.setproctitle('hello world'); $0 == $_0 or Process.setproctitle('$0 changed!'); sleep 60") + + pid = spawn(EnvUtil.rubybin, "test-script") + ps = nil + 10.times do + sleep 0.1 + ps = `ps -p #{pid} -o command` + break if /hello world/ =~ ps + end + assert_match(/hello world/, ps) + Process.kill :KILL, pid + Process.wait(pid) + end + end + module SEGVTest opts = {} if /mswin|mingw/ =~ RUBY_PLATFORM