Module: Process

Defined in:
process.c

Defined Under Namespace

Modules: GID, Sys, UID Classes: Status

Constant Summary collapse

WNOHANG =

see Process.wait

INT2FIX(0)
WUNTRACED =

see Process.wait

INT2FIX(0)
PRIO_PROCESS =

see Process.setpriority

INT2FIX(PRIO_PROCESS)
PRIO_PGRP =

see Process.setpriority

INT2FIX(PRIO_PGRP)
PRIO_USER =

see Process.setpriority

INT2FIX(PRIO_USER)
RLIM_SAVED_MAX =

see Process.setrlimit

v
RLIM_INFINITY =

see Process.setrlimit

inf
RLIM_SAVED_CUR =

see Process.setrlimit

v
RLIMIT_AS =

Maximum size of the process's virtual memory (address space) in bytes.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_AS)
RLIMIT_CORE =

Maximum size of the core file.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_CORE)
RLIMIT_CPU =

CPU time limit in seconds.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_CPU)
RLIMIT_DATA =

Maximum size of the process's data segment.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_DATA)
RLIMIT_FSIZE =

Maximum size of files that the process may create.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_FSIZE)
RLIMIT_MEMLOCK =

Maximum number of bytes of memory that may be locked into RAM.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_MEMLOCK)
RLIMIT_MSGQUEUE =

Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_MSGQUEUE)
RLIMIT_NICE =

Specifies a ceiling to which the process's nice value can be raised.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_NICE)
RLIMIT_NOFILE =

Specifies a value one greater than the maximum file descriptor number that can be opened by this process.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_NOFILE)
RLIMIT_NPROC =

The maximum number of processes that can be created for the real user ID of the calling process.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_NPROC)
RLIMIT_RSS =

Specifies the limit (in pages) of the process's resident set.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_RSS)
RLIMIT_RTPRIO =

Specifies a ceiling on the real-time priority that may be set for this process.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_RTPRIO)
RLIMIT_RTTIME =

Specifies limit on CPU time this process scheduled under a real-time scheduling policy can consume.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_RTTIME)
RLIMIT_SBSIZE =

Maximum size of the socket buffer.

INT2FIX(RLIMIT_SBSIZE)
RLIMIT_SIGPENDING =

Specifies a limit on the number of signals that may be queued for the real user ID of the calling process.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_SIGPENDING)
RLIMIT_STACK =

Maximum size of the stack, in bytes.

see the system getrlimit(2) manual for details.

INT2FIX(RLIMIT_STACK)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.abortObject .Kernel::abort([msg]) ⇒ Object .Process::abort([msg]) ⇒ Object

Terminate execution immediately, effectively by calling Kernel.exit(false). If msg is given, it is written to STDERR prior to terminating.


3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
# File 'process.c', line 3619

VALUE
rb_f_abort(int argc, VALUE *argv)
{
    rb_secure(4);
    if (argc == 0) {
	if (!NIL_P(GET_THREAD()->errinfo)) {
	    ruby_error_print();
	}
	rb_exit(EXIT_FAILURE);
    }
    else {
	VALUE args[2];

	rb_scan_args(argc, argv, "1", &args[1]);
	StringValue(argv[0]);
	rb_io_puts(argc, argv, rb_stderr);
	args[0] = INT2NUM(EXIT_FAILURE);
	rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
    }

    UNREACHABLE;
}

.daemon0 .daemon(nochdir = nil, noclose = nil) ⇒ 0

Detach the process from controlling terminal and run in the background as system daemon. Unless the argument nochdir is true (i.e. non false), it changes the current working directory to the root ("/"). Unless the argument noclose is true, daemon() will redirect standard input, standard output and standard error to /dev/null. Return zero on success, or raise one of Errno::*.

Overloads:

  • .daemon0

    Returns:

    • (0)
  • .daemon(nochdir = nil, noclose = nil) ⇒ 0

    Returns:

    • (0)

5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
# File 'process.c', line 5648

static VALUE
proc_daemon(int argc, VALUE *argv)
{
    VALUE nochdir, noclose;
    int n;

    rb_secure(2);
    rb_scan_args(argc, argv, "02", &nochdir, &noclose);

    prefork();
    n = rb_daemon(RTEST(nochdir), RTEST(noclose));
    if (n < 0) rb_sys_fail("daemon");
    return INT2FIX(n);
}

.detach(pid) ⇒ Object

Some operating systems retain the status of terminated child processes until the parent collects that status (normally using some variant of wait(). If the parent never collects this status, the child stays around as a zombie process. Process::detach prevents this by setting up a separate Ruby thread whose sole job is to reap the status of the process pid when it terminates. Use detach only when you do not intent to explicitly wait for the child to terminate.

The waiting thread returns the exit status of the detached process when it terminates, so you can use Thread#join to know the result. If specified pid is not a valid child process ID, the thread returns nil immediately.

The waiting thread has pid method which returns the pid.

In this first example, we don't reap the first child process, so it appears as a zombie in the process status display.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

produces:

27389 Z

In the next example, Process::detach is used to reap the child automatically.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.detach(p1)
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

(produces no output)


1032
1033
1034
1035
1036
1037
# File 'process.c', line 1032

static VALUE
proc_detach(VALUE obj, VALUE pid)
{
    rb_secure(2);
    return rb_detach_process(NUM2PIDT(pid));
}

.egidFixnum .Process::GID.eidFixnum .Process::Sys.geteidFixnum

Returns the effective group ID for this process. Not available on all platforms.

Process.egid   #=> 500

Overloads:


6051
6052
6053
6054
6055
6056
6057
# File 'process.c', line 6051

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}

.egid=Object

.euidFixnum .Process::UID.eidFixnum .Process::Sys.geteuidFixnum

Returns the effective user ID for this process.

Process.euid   #=> 501

Overloads:


5925
5926
5927
5928
5929
5930
# File 'process.c', line 5925

static VALUE
proc_geteuid(VALUE obj)
{
    rb_uid_t euid = geteuid();
    return UIDT2NUM(euid);
}

.euid=(user) ⇒ Object

Sets the effective user ID for this process. Not available on all platforms.


5964
5965
5966
5967
5968
5969
5970
5971
# File 'process.c', line 5964

static VALUE
proc_seteuid_m(VALUE mod, VALUE euid)
{
    PREPARE_GETPWNAM;
    check_uid_switch();
    proc_seteuid(OBJ2UID(euid));
    return euid;
}

.exec([env,][,options]) ⇒ Object

Replaces the current process by running the given external command. command... is one of following forms.

commandline                 : command line string which is passed to the standard shell
cmdname, arg1, ...          : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)

If single string is given as the command, it is taken as a command line that is subject to shell expansion before being executed.

The standard shell means always "/bin/sh" on Unix-like systems, ENV["RUBYSHELL"] or ENV["COMSPEC"] on Windows NT series, and similar.

If two or more string given, the first is taken as a command name and the rest are passed as parameters to command with no shell expansion.

If a two-element array at the beginning of the command, the first element is the command to be executed, and the second argument is used as the argv[0] value, which may show up in process listings.

In order to execute the command, one of the exec(2) system calls is used, so the running command may inherit some of the environment of the original program (including open file descriptors). This behavior is modified by env and options. See spawn for details.

Raises SystemCallError if the command couldn't execute (typically Errno::ENOENT when it was not found).

This method modifies process attributes according to options (details described in spawn) before exec(2) system call. The modified attributes may be retained when exec(2) system call fails. For example, hard resource limits is not restorable. If it is not acceptable, consider to create a child process using spawn or system.

exec "echo *"       # echoes list of files in current directory
# never get here

exec "echo", "*"    # echoes an asterisk
# never get here

2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
# File 'process.c', line 2386

VALUE
rb_f_exec(int argc, VALUE *argv)
{
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;
#define CHILD_ERRMSG_BUFLEN 80
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };

    execarg_obj = rb_execarg_new(argc, argv, TRUE);
    eargp = rb_execarg_get(execarg_obj);
    rb_execarg_fixup(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

#if defined(__APPLE__) || defined(__HAIKU__)
    rb_exec_without_timer_thread(eargp, errmsg, sizeof(errmsg));
#else
    rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
#endif
    RB_GC_GUARD(execarg_obj);
    if (errmsg[0])
        rb_sys_fail(errmsg);
    rb_sys_fail_str(fail_str);
    return Qnil;		/* dummy */
}

.exit(status = true) ⇒ Object .Kernel::exit(status = true) ⇒ Object .Process::exit(status = true) ⇒ Object

Initiates the termination of the Ruby script by raising the SystemExit exception. This exception may be caught. The optional parameter is used to return a status code to the invoking environment. true and FALSE of status means success and failure respectively. The interpretation of other integer values are system dependent.

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception"
end
puts "after begin block"

produces:

rescued a SystemExit exception
after begin block

Just prior to termination, Ruby executes any at_exit functions (see Kernel::at_exit) and runs any object finalizers (see ObjectSpace::define_finalizer).

at_exit { puts "at_exit function" }
ObjectSpace.define_finalizer("string",  proc { puts "in finalizer" })
exit

produces:

at_exit function
in finalizer

3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
# File 'process.c', line 3589

VALUE
rb_f_exit(int argc, VALUE *argv)
{
    VALUE status;
    int istatus;

    rb_secure(4);
    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
	istatus = exit_status_code(status);
    }
    else {
	istatus = EXIT_SUCCESS;
    }
    rb_exit(istatus);

    UNREACHABLE;
}

.exit!(status = false) ⇒ Object

Exits the process immediately. No exit handlers are run. status is returned to the underlying system as the exit status.

Process.exit!(true)

3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
# File 'process.c', line 3515

static VALUE
rb_f_exit_bang(int argc, VALUE *argv, VALUE obj)
{
    VALUE status;
    int istatus;

    rb_secure(4);
    if (argc > 0 && rb_scan_args(argc, argv, "01", &status) == 1) {
	istatus = exit_status_code(status);
    }
    else {
	istatus = EXIT_FAILURE;
    }
    _exit(istatus);

    UNREACHABLE;
}

.fork { ... } ⇒ Fixnum? .fork { ... } ⇒ Fixnum?

Creates a subprocess. If a block is specified, that block is run in the subprocess, and the subprocess terminates with a status of zero. Otherwise, the fork call returns twice, once in the parent, returning the process ID of the child, and once in the child, returning nil. The child process can exit using Kernel.exit! to avoid running any at_exit functions. The parent process should use Process.wait to collect the termination statuses of its children or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

The thread calling fork is the only thread in the created child process. fork doesn't copy other threads.

If fork is not usable, Process.respond_to?(:fork) returns false.

Overloads:


3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
# File 'process.c', line 3451

static VALUE
rb_f_fork(VALUE obj)
{
    rb_pid_t pid;

    rb_secure(2);

    switch (pid = rb_fork_ruby(NULL)) {
      case 0:
	rb_thread_atfork();
	if (rb_block_given_p()) {
	    int status;

	    rb_protect(rb_yield, Qundef, &status);
	    ruby_stop(status);
	}
	return Qnil;

      case -1:
	rb_sys_fail("fork(2)");
	return Qnil;

      default:
	return PIDT2NUM(pid);
    }
}

.getpgid(pid) ⇒ Integer

Returns the process group ID for the given process id. Not available on all platforms.

Process.getpgid(Process.ppid())   #=> 25527

Returns:


4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
# File 'process.c', line 4187

static VALUE
proc_getpgid(VALUE obj, VALUE pid)
{
    rb_pid_t i;

    rb_secure(2);
    i = getpgid(NUM2PIDT(pid));
    if (i < 0) rb_sys_fail(0);
    return PIDT2NUM(i);
}

.getpgrpInteger

Returns the process group ID for this process. Not available on all platforms.

Process.getpgid(0)   #=> 25527
Process.getpgrp      #=> 25527

Returns:


4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
# File 'process.c', line 4126

static VALUE
proc_getpgrp(void)
{
    rb_pid_t pgrp;

    rb_secure(2);
#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
    pgrp = getpgrp();
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#else /* defined(HAVE_GETPGID) */
    pgrp = getpgid(0);
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#endif
}

.getpriority(kind, integer) ⇒ Fixnum

Gets the scheduling priority for specified process, process group, or user. kind indicates the kind of entity to find: one of Process::PRIO_PGRP, Process::PRIO_USER, or Process::PRIO_PROCESS. integer is an id indicating the particular process, process group, or user (an id of 0 means current). Lower priorities are more favorable for scheduling. Not available on all platforms.

Process.getpriority(Process::PRIO_USER, 0)      #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)   #=> 19

Returns:


4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
# File 'process.c', line 4339

static VALUE
proc_getpriority(VALUE obj, VALUE which, VALUE who)
{
    int prio, iwhich, iwho;

    rb_secure(2);
    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);

    errno = 0;
    prio = getpriority(iwhich, iwho);
    if (errno) rb_sys_fail(0);
    return INT2FIX(prio);
}

.getrlimit(resource) ⇒ Array

Gets the resource limit of the process. cur_limit means current (soft) limit and max_limit means maximum (hard) limit.

resource indicates the kind of resource to limit. It is specified as a symbol such as :CORE, a string such as "CORE" or a constant such as Process::RLIMIT_CORE. See Process.setrlimit for details.

cur_limit and max_limit may be Process::RLIM_INFINITY, Process::RLIM_SAVED_MAX or Process::RLIM_SAVED_CUR. See Process.setrlimit and the system getrlimit(2) manual for details.

Returns:


4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
# File 'process.c', line 4609

static VALUE
proc_getrlimit(VALUE obj, VALUE resource)
{
    struct rlimit rlim;

    rb_secure(2);

    if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
	rb_sys_fail("getrlimit");
    }
    return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
}

.getsidInteger .getsid(pid) ⇒ Integer

Returns the session ID for for the given process id. If not give, return current process sid. Not available on all platforms.

Process.getsid()                #=> 27422
Process.getsid(0)               #=> 27422
Process.getsid(Process.pid())   #=> 27422

Overloads:


4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
# File 'process.c', line 4241

static VALUE
proc_getsid(int argc, VALUE *argv)
{
    rb_pid_t sid;
    VALUE pid;

    rb_secure(2);
    rb_scan_args(argc, argv, "01", &pid);

    if (NIL_P(pid))
	pid = INT2NUM(0);

    sid = getsid(NUM2PIDT(pid));
    if (sid < 0) rb_sys_fail(0);
    return PIDT2NUM(sid);
}

.gidFixnum .Process::GID.ridFixnum .Process::Sys.getgidFixnum

Returns the (real) group ID for this process.

Process.gid   #=> 500

Overloads:


5366
5367
5368
5369
5370
5371
# File 'process.c', line 5366

static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}

.gid=(fixnum) ⇒ Fixnum

Sets the group ID for this process.

Returns:


5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
# File 'process.c', line 5382

static VALUE
proc_setgid(VALUE obj, VALUE id)
{
    rb_gid_t gid;
    PREPARE_GETGRNAM;

    check_gid_switch();

    gid = OBJ2GID(id);
#if defined(HAVE_SETRESGID)
    if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREGID
    if (setregid(gid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRGID
    if (setrgid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
    {
	if (getegid() == gid) {
	    if (setgid(gid) < 0) rb_sys_fail(0);
	}
	else {
	    rb_notimplement();
	}
    }
#endif
    return GIDT2NUM(gid);
}

.groupsArray

Get an Array of the gids of groups in the supplemental group access list for this process.

Process.groups   #=> [27, 6, 10, 11]

Returns:


5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
# File 'process.c', line 5475

static VALUE
proc_getgroups(VALUE obj)
{
    VALUE ary;
    int i, ngroups;
    rb_gid_t *groups;

    ngroups = getgroups(0, NULL);
    if (ngroups == -1)
	rb_sys_fail(0);

    groups = ALLOCA_N(rb_gid_t, ngroups);

    ngroups = getgroups(ngroups, groups);
    if (ngroups == -1)
	rb_sys_fail(0);

    ary = rb_ary_new();
    for (i = 0; i < ngroups; i++)
	rb_ary_push(ary, GIDT2NUM(groups[i]));

    return ary;
}

.groups=(array) ⇒ Array

Set the supplemental group access list to the given Array of group IDs.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.groups = [27, 6, 10, 11]   #=> [27, 6, 10, 11]
Process.groups   #=> [27, 6, 10, 11]

Returns:


5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
# File 'process.c', line 5517

static VALUE
proc_setgroups(VALUE obj, VALUE ary)
{
    int ngroups, i;
    rb_gid_t *groups;
    PREPARE_GETGRNAM;

    Check_Type(ary, T_ARRAY);

    ngroups = RARRAY_LENINT(ary);
    if (ngroups > maxgroups())
	rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());

    groups = ALLOCA_N(rb_gid_t, ngroups);

    for (i = 0; i < ngroups; i++) {
	VALUE g = RARRAY_PTR(ary)[i];

	groups[i] = OBJ2GID(g);
    }

    if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
	rb_sys_fail(0);

    return proc_getgroups(obj);
}

.initgroups(username, gid) ⇒ Array

Initializes the supplemental group access list by reading the system group database and using all groups of which the given user is a member. The group with the specified gid is also added to the list. Returns the resulting Array of the gids of all the groups in the supplementary group access list. Not available on all platforms.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.initgroups( "mgranger", 30 )   #=> [30, 6, 10, 11]
Process.groups   #=> [30, 6, 10, 11]

Returns:


5566
5567
5568
5569
5570
5571
5572
5573
5574
# File 'process.c', line 5566

static VALUE
proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
{
    PREPARE_GETGRNAM;
    if (initgroups(StringValuePtr(uname), OBJ2GID(base_grp)) != 0) {
	rb_sys_fail(0);
    }
    return proc_getgroups(obj);
}

.kill(signal, pid, ...) ⇒ Fixnum

Sends the given signal to the specified process id(s) if pid is positive. If pid is zero signal is sent to all processes whose group ID is equal to the group ID of the process. signal may be an integer signal number or a POSIX signal name (either with or without a SIG prefix). If signal is negative (or starts with a minus sign), kills process groups instead of processes. Not all signals are available on all platforms.

pid = fork do
   Signal.trap("HUP") { puts "Ouch!"; exit }
   # ... do some work ...
end
# ...
Process.kill("HUP", pid)
Process.wait

produces:

Ouch!

If signal is an integer but wrong for signal, Errno::EINVAL or RangeError will be raised. Otherwise unless signal is a String or a Symbol, and a known signal name, ArgumentError will be raised.

Also, Errno::ESRCH or RangeError for invalid pid, Errno::EPERM when failed because of no privilege, will be raised. In these cases, signals may have been sent to preceding processes.

Returns:


363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'signal.c', line 363

VALUE
rb_f_kill(int argc, VALUE *argv)
{
#ifndef HAS_KILLPG
#define killpg(pg, sig) kill(-(pg), (sig))
#endif
    int negative = 0;
    int sig;
    int i;
    volatile VALUE str;
    const char *s;

    rb_secure(2);
    rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);

    switch (TYPE(argv[0])) {
      case T_FIXNUM:
	sig = FIX2INT(argv[0]);
	break;

      case T_SYMBOL:
	s = rb_id2name(SYM2ID(argv[0]));
	if (!s) rb_raise(rb_eArgError, "bad signal");
	goto str_signal;

      case T_STRING:
	s = RSTRING_PTR(argv[0]);
      str_signal:
	if (s[0] == '-') {
	    negative++;
	    s++;
	}
	if (strncmp("SIG", s, 3) == 0)
	    s += 3;
	if ((sig = signm2signo(s)) == 0)
	    rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);

	if (negative)
	    sig = -sig;
	break;

      default:
	str = rb_check_string_type(argv[0]);
	if (!NIL_P(str)) {
	    s = RSTRING_PTR(str);
	    goto str_signal;
	}
	rb_raise(rb_eArgError, "bad signal type %s",
		 rb_obj_classname(argv[0]));
	break;
    }

    if (sig < 0) {
	sig = -sig;
	for (i=1; i<argc; i++) {
	    if (killpg(NUM2PIDT(argv[i]), sig) < 0)
		rb_sys_fail(0);
	}
    }
    else {
	for (i=1; i<argc; i++) {
	    if (kill(NUM2PIDT(argv[i]), sig) < 0)
		rb_sys_fail(0);
	}
    }
    return INT2FIX(i-1);
}

.maxgroupsFixnum

Returns the maximum number of gids allowed in the supplemental group access list.

Process.maxgroups   #=> 32

Returns:


5590
5591
5592
5593
5594
# File 'process.c', line 5590

static VALUE
proc_getmaxgroups(VALUE obj)
{
    return INT2FIX(maxgroups());
}

.maxgroups=(fixnum) ⇒ Fixnum

Sets the maximum number of gids allowed in the supplemental group access list.

Returns:


5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
# File 'process.c', line 5608

static VALUE
proc_setmaxgroups(VALUE obj, VALUE val)
{
    int ngroups = FIX2INT(val);
    int ngroups_max = get_sc_ngroups_max();

    if (ngroups <= 0)
	rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);

    if (ngroups > RB_MAX_GROUPS)
	ngroups = RB_MAX_GROUPS;

    if (ngroups_max > 0 && ngroups > ngroups_max)
	ngroups = ngroups_max;

    _maxgroups = ngroups;

    return INT2FIX(_maxgroups);
}

.pidFixnum

Returns the process id of this process. Not available on all platforms.

Process.pid   #=> 27415

Returns:


205
206
207
208
209
210
# File 'process.c', line 205

static VALUE
get_pid(void)
{
    rb_secure(2);
    return PIDT2NUM(getpid());
}

.ppidFixnum

Returns the process id of the parent of this process. Returns untrustworthy value on Win32/64. Not available on all platforms.

puts "I am #{Process.pid}"
Process.fork { puts "Dad is #{Process.ppid}" }

produces:

I am 27417
Dad is 27417

Returns:


229
230
231
232
233
234
# File 'process.c', line 229

static VALUE
get_ppid(void)
{
    rb_secure(2);
    return PIDT2NUM(getppid());
}

.setpgid(pid, integer) ⇒ 0

Sets the process group ID of pid (0 indicates this process) to integer. Not available on all platforms.

Returns:

  • (0)

4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
# File 'process.c', line 4211

static VALUE
proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
{
    rb_pid_t ipid, ipgrp;

    rb_secure(2);
    ipid = NUM2PIDT(pid);
    ipgrp = NUM2PIDT(pgrp);

    if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
    return INT2FIX(0);
}

.setpgrp0

Equivalent to setpgid(0,0). Not available on all platforms.

Returns:

  • (0)

4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
# File 'process.c', line 4156

static VALUE
proc_setpgrp(void)
{
    rb_secure(2);
  /* check for posix setpgid() first; this matches the posix */
  /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
  /* this confusion. */
#ifdef HAVE_SETPGID
    if (setpgid(0,0) < 0) rb_sys_fail(0);
#elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
    if (setpgrp() < 0) rb_sys_fail(0);
#endif
    return INT2FIX(0);
}

.setpriority(kind, integer, priority) ⇒ 0

See Process#getpriority.

Process.setpriority(Process::PRIO_USER, 0, 19)      #=> 0
Process.setpriority(Process::PRIO_PROCESS, 0, 19)   #=> 0
Process.getpriority(Process::PRIO_USER, 0)          #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)       #=> 19

Returns:

  • (0)

4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
# File 'process.c', line 4371

static VALUE
proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
{
    int iwhich, iwho, iprio;

    rb_secure(2);
    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);
    iprio  = NUM2INT(prio);

    if (setpriority(iwhich, iwho, iprio) < 0)
	rb_sys_fail(0);
    return INT2FIX(0);
}

.setrlimit(resource, cur_limit, max_limit) ⇒ nil .setrlimit(resource, cur_limit) ⇒ nil

Sets the resource limit of the process. cur_limit means current (soft) limit and max_limit means maximum (hard) limit.

If max_limit is not given, cur_limit is used.

resource indicates the kind of resource to limit. It should be a symbol such as :CORE, a string such as "CORE" or a constant such as Process::RLIMIT_CORE. The available resources are OS dependent. Ruby may support following resources.

AS

total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)

CORE

core size (bytes) (SUSv3)

CPU

CPU time (seconds) (SUSv3)

DATA

data segment (bytes) (SUSv3)

FSIZE

file size (bytes) (SUSv3)

MEMLOCK

total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)

MSGQUEUE

allocation for POSIX message queues (bytes) (GNU/Linux)

NICE

ceiling on process's nice(2) value (number) (GNU/Linux)

NOFILE

file descriptors (number) (SUSv3)

NPROC

number of processes for the user (number) (4.4BSD, GNU/Linux)

RSS

resident memory size (bytes) (4.2BSD, GNU/Linux)

RTPRIO

ceiling on the process's real-time priority (number) (GNU/Linux)

RTTIME

CPU time for real-time process (us) (GNU/Linux)

SBSIZE

all socket buffers (bytes) (NetBSD, FreeBSD)

SIGPENDING

number of queued signals allowed (signals) (GNU/Linux)

STACK

stack size (bytes) (SUSv3)

cur_limit and max_limit may be :INFINITY, "INFINITY" or Process::RLIM_INFINITY, which means that the resource is not limited. They may be Process::RLIM_SAVED_MAX, Process::RLIM_SAVED_CUR and corresponding symbols and strings too. See system setrlimit(2) manual for details.

The following example raises the soft limit of core size to the hard limit to try to make core dump possible.

Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])

Overloads:

  • .setrlimit(resource, cur_limit, max_limit) ⇒ nil

    Returns:

    • (nil)
  • .setrlimit(resource, cur_limit) ⇒ nil

    Returns:

    • (nil)

4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
# File 'process.c', line 4677

static VALUE
proc_setrlimit(int argc, VALUE *argv, VALUE obj)
{
    VALUE resource, rlim_cur, rlim_max;
    struct rlimit rlim;

    rb_secure(2);

    rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
    if (rlim_max == Qnil)
        rlim_max = rlim_cur;

    rlim.rlim_cur = rlimit_resource_value(rlim_cur);
    rlim.rlim_max = rlimit_resource_value(rlim_max);

    if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
	rb_sys_fail("setrlimit");
    }
    return Qnil;
}

.setsidFixnum

Establishes this process as a new session and process group leader, with no controlling tty. Returns the session id. Not available on all platforms.

Process.setsid   #=> 27422

Returns:


4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
# File 'process.c', line 4278

static VALUE
proc_setsid(void)
{
    rb_pid_t pid;

    rb_secure(2);
    pid = setsid();
    if (pid < 0) rb_sys_fail(0);
    return PIDT2NUM(pid);
}

.spawn([env,][,options]) ⇒ Object .spawn([env,][,options]) ⇒ Object

spawn executes specified command and return its pid.

This method doesn't wait for end of the command. The parent process should use Process.wait to collect the termination status of its child or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

spawn has bunch of options to specify process attributes:

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (no shell)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : don't clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join to specified process group
    :pgroup => nil       : don't change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : don't create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => true  : don't inherit
  current directory:
    :chdir => str

If a hash is given as env, the environment is updated by env before exec(2) in the child process. If a pair in env has nil as the value, the variable is deleted.

# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)

If a hash is given as options, it specifies process group, create new process group, resource limit, current directory, umask and redirects for the child process. Also, it can be specified to clear environment variables.

The :unsetenv_others key in options specifies to clear environment variables, other than specified by env.

pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only

The :pgroup key in options specifies a process group. The corresponding value should be true, zero or positive integer. true and zero means the process should be a process leader of a new process group. Other values specifies a process group to be belongs.

pid = spawn(command, :pgroup=>true) # process leader
pid = spawn(command, :pgroup=>10) # belongs to the process group 10

The :new_pgroup key in options specifies to pass CREATE_NEW_PROCESS_GROUP flag to CreateProcessW() that is Windows API. This option is only for Windows. true means the new process is the root process of the new process group. The new process has CTRL+C disabled. This flag is necessary for Process.kill(:SIGINT, pid) on the subprocess. :new_pgroup is false by default.

pid = spawn(command, :new_pgroup=>true)  # new process group
pid = spawn(command, :new_pgroup=>false) # same process group

The :rlimit_foo key specifies a resource limit. foo should be one of resource types such as core. The corresponding value should be an integer or an array which have one or two integers: same as cur_limit and max_limit arguments for Process.setrlimit.

cur, max = Process.getrlimit(:CORE)
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
pid = spawn(command, :rlimit_core=>max) # enable core dump
pid = spawn(command, :rlimit_core=>0) # never dump core.

The :umask key in options specifies the umask.

pid = spawn(command, :umask=>077)

The :in, :out, :err, a fixnum, an IO and an array key specifies a redirection. The redirection maps a file descriptor in the child process.

For example, stderr can be merged into stdout as follows:

pid = spawn(command, :err=>:out)
pid = spawn(command, 2=>1)
pid = spawn(command, STDERR=>:out)
pid = spawn(command, STDERR=>STDOUT)

The hash keys specifies a file descriptor in the child process started by spawn. :err, 2 and STDERR specifies the standard error stream (stderr).

The hash values specifies a file descriptor in the parent process which invokes spawn. :out, 1 and STDOUT specifies the standard output stream (stdout).

In the above example, the standard output in the child process is not specified. So it is inherited from the parent process.

The standard input stream (stdin) can be specified by :in, 0 and STDIN.

A filename can be specified as a hash value.

pid = spawn(command, :in=>"/dev/null") # read mode
pid = spawn(command, :out=>"/dev/null") # write mode
pid = spawn(command, :err=>"log") # write mode
pid = spawn(command, 3=>"/dev/null") # read mode

For stdout and stderr, it is opened in write mode. Otherwise read mode is used.

For specifying flags and permission of file creation explicitly, an array is used instead.

pid = spawn(command, :in=>["file"]) # read mode is assumed
pid = spawn(command, :in=>["file", "r"])
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
pid = spawn(command, :out=>["log", "w", 0600])
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])

The array specifies a filename, flags and permission. The flags can be a string or an integer. If the flags is omitted or nil, File::RDONLY is assumed. The permission should be an integer. If the permission is omitted or nil, 0644 is assumed.

If an array of IOs and integers are specified as a hash key, all the elements are redirected.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, [:out, :err]=>["log", "w"])

Another way to merge multiple file descriptors is [:child, fd]. [:child, fd] means the file descriptor in the child process. This is different from fd. For example, :err=>:out means redirecting child stderr to parent stdout. But :err=>[:child, :out] means redirecting child stderr to child stdout. They differ if stdout is redirected in the child process as follows.

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])

[:child, :out] can be used to merge stderr into stdout in IO.popen. In this case, IO.popen redirects stdout to a pipe in the child process and [:child, :out] refers the redirected stdout.

io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
p io.read #=> "out\nerr\n"

The :chdir key in options specifies the current directory.

pid = spawn(command, :chdir=>"/var/tmp")

spawn closes all non-standard unspecified descriptors by default. The "standard" descriptors are 0, 1 and 2. This behavior is specified by :close_others option. :close_others doesn't affect the standard descriptors which are closed only if :close is specified explicitly.

pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...

:close_others is true by default for spawn and IO.popen.

Note that fds which close-on-exec flag is already set are closed regardless of :close_others option.

So IO.pipe and spawn can be used as IO.popen.

# similar to r = IO.popen(command)
r, w = IO.pipe
pid = spawn(command, :out=>w)   # r, w is closed in the child process.
w.close

:close is specified as a hash value to close a fd individually.

f = open(foo)
system(command, f=>:close)        # don't inherit f.

If a file descriptor need to be inherited, io=>io can be used.

# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read

It is also possible to exchange file descriptors.

pid = spawn(command, :out=>:err, :err=>:out)

The hash keys specify file descriptors in the child process. The hash values specifies file descriptors in the parent process. So the above specifies exchanging stdout and stderr. Internally, spawn uses an extra file descriptor to resolve such cyclic file descriptor mapping.

See Kernel.exec for the standard shell.


4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
# File 'process.c', line 4047

static VALUE
rb_f_spawn(int argc, VALUE *argv)
{
    rb_pid_t pid;
    char errmsg[CHILD_ERRMSG_BUFLEN] = { '\0' };
    VALUE execarg_obj, fail_str;
    struct rb_execarg *eargp;

    execarg_obj = rb_execarg_new(argc, argv, TRUE);
    eargp = rb_execarg_get(execarg_obj);
    rb_execarg_fixup(execarg_obj);
    fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;

    pid = rb_spawn_process(eargp, errmsg, sizeof(errmsg));
    RB_GC_GUARD(execarg_obj);

    if (pid == -1) {
	const char *prog = errmsg;
	if (!prog[0]) {
	    rb_sys_fail_str(fail_str);
	}
	rb_sys_fail(prog);
    }
#if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
    return PIDT2NUM(pid);
#else
    return Qnil;
#endif
}

.timesaStructTms

Returns a Tms structure (see Struct::Tms) that contains user and system CPU times for this process, and also for children processes.

t = Process.times
[ t.utime, t.stime, t.cutime, t.cstime ]   #=> [0.0, 0.02, 0.00, 0.00]

Returns:

  • (aStructTms)

6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
# File 'process.c', line 6538

VALUE
rb_proc_times(VALUE obj)
{
    const double hertz =
#ifdef HAVE__SC_CLK_TCK
	(double)sysconf(_SC_CLK_TCK);
#else
#ifndef HZ
# ifdef CLK_TCK
#   define HZ CLK_TCK
# else
#   define HZ 60
# endif
#endif /* HZ */
	HZ;
#endif
    struct tms buf;
    volatile VALUE utime, stime, cutime, sctime;

    times(&buf);
    return rb_struct_new(rb_cProcessTms,
			 utime = DBL2NUM(buf.tms_utime / hertz),
			 stime = DBL2NUM(buf.tms_stime / hertz),
			 cutime = DBL2NUM(buf.tms_cutime / hertz),
			 sctime = DBL2NUM(buf.tms_cstime / hertz));
}

.uidFixnum .Process::UID.ridFixnum .Process::Sys.getuidFixnum

Returns the (real) user ID of this process.

Process.uid   #=> 501

Overloads:


4958
4959
4960
4961
4962
4963
# File 'process.c', line 4958

static VALUE
proc_getuid(VALUE obj)
{
    rb_uid_t uid = getuid();
    return UIDT2NUM(uid);
}

.uid=(user) ⇒ Numeric

Sets the (user) user ID for this process. Not available on all platforms.

Returns:


4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
# File 'process.c', line 4975

static VALUE
proc_setuid(VALUE obj, VALUE id)
{
    rb_uid_t uid;
    PREPARE_GETPWNAM;

    check_uid_switch();

    uid = OBJ2UID(id);
#if defined(HAVE_SETRESUID)
    if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREUID
    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRUID
    if (setruid(uid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETUID
    {
	if (geteuid() == uid) {
	    if (setuid(uid) < 0) rb_sys_fail(0);
	}
	else {
	    rb_notimplement();
	}
    }
#endif
    return id;
}

.waitFixnum .wait(pid = -1, flags = 0) ⇒ Fixnum .waitpid(pid = -1, flags = 0) ⇒ Fixnum

Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object containing information on that process. Which child it waits on depends on the value of pid:

> 0

Waits for the child whose process ID equals pid.

0

Waits for any child whose process group ID equals that of the calling process.

-1

Waits for any child process (the default if no pid is given).

< -1

Waits for any child whose process group ID equals the absolute value of pid.

The flags argument may be a logical or of the flag values Process::WNOHANG (do not block if no child available) or Process::WUNTRACED (return stopped children that haven't been reported). Not all flags are available on all platforms, but a flag value of zero will work on all platforms.

Calling this method raises a SystemCallError if there are no child processes. Not available on all platforms.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900

Overloads:


833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# File 'process.c', line 833

static VALUE
proc_wait(int argc, VALUE *argv)
{
    VALUE vpid, vflags;
    rb_pid_t pid;
    int flags, status;

    rb_secure(2);
    flags = 0;
    if (argc == 0) {
	pid = -1;
    }
    else {
	rb_scan_args(argc, argv, "02", &vpid, &vflags);
	pid = NUM2PIDT(vpid);
	if (argc == 2 && !NIL_P(vflags)) {
	    flags = NUM2UINT(vflags);
	}
    }
    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
	rb_sys_fail(0);
    if (pid == 0) {
	rb_last_status_clear();
	return Qnil;
    }
    return PIDT2NUM(pid);
}

.wait2(pid = -1, flags = 0) ⇒ Array .waitpid2(pid = -1, flags = 0) ⇒ Array

Waits for a child process to exit (see Process::waitpid for exact semantics) and returns an array containing the process id and the exit status (a Process::Status object) of that child. Raises a SystemCallError if there are no child processes.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

Overloads:

  • .wait2(pid = -1, flags = 0) ⇒ Array

    Returns:

  • .waitpid2(pid = -1, flags = 0) ⇒ Array

    Returns:


878
879
880
881
882
883
884
# File 'process.c', line 878

static VALUE
proc_wait2(int argc, VALUE *argv)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}

.waitallArray

Waits for all children, returning an array of pid/status pairs (where status is a Process::Status object).

fork { sleep 0.2; exit 2 }   #=> 27432
fork { sleep 0.1; exit 1 }   #=> 27433
fork {            exit 0 }   #=> 27434
p Process.waitall

produces:

[[30982, #<Process::Status: pid 30982 exit 0>],
 [30979, #<Process::Status: pid 30979 exit 1>],
 [30976, #<Process::Status: pid 30976 exit 2>]]

Returns:


907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
# File 'process.c', line 907

static VALUE
proc_waitall(void)
{
    VALUE result;
    rb_pid_t pid;
    int status;

    rb_secure(2);
    result = rb_ary_new();
#ifdef NO_WAITPID
    if (pid_tbl) {
	st_foreach(pid_tbl, waitall_each, result);
    }
#else
    rb_last_status_clear();
#endif

    for (pid = -1;;) {
#ifdef NO_WAITPID
	pid = wait(&status);
#else
	pid = rb_waitpid(-1, &status, 0);
#endif
	if (pid == -1) {
	    if (errno == ECHILD)
		break;
#ifdef NO_WAITPID
	    if (errno == EINTR) {
		rb_thread_schedule();
		continue;
	    }
#endif
	    rb_sys_fail(0);
	}
#ifdef NO_WAITPID
	rb_last_status_set(status, pid);
#endif
	rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
    }
    return result;
}

.waitFixnum .wait(pid = -1, flags = 0) ⇒ Fixnum .waitpid(pid = -1, flags = 0) ⇒ Fixnum

Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object containing information on that process. Which child it waits on depends on the value of pid:

> 0

Waits for the child whose process ID equals pid.

0

Waits for any child whose process group ID equals that of the calling process.

-1

Waits for any child process (the default if no pid is given).

< -1

Waits for any child whose process group ID equals the absolute value of pid.

The flags argument may be a logical or of the flag values Process::WNOHANG (do not block if no child available) or Process::WUNTRACED (return stopped children that haven't been reported). Not all flags are available on all platforms, but a flag value of zero will work on all platforms.

Calling this method raises a SystemCallError if there are no child processes. Not available on all platforms.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900

Overloads:


833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# File 'process.c', line 833

static VALUE
proc_wait(int argc, VALUE *argv)
{
    VALUE vpid, vflags;
    rb_pid_t pid;
    int flags, status;

    rb_secure(2);
    flags = 0;
    if (argc == 0) {
	pid = -1;
    }
    else {
	rb_scan_args(argc, argv, "02", &vpid, &vflags);
	pid = NUM2PIDT(vpid);
	if (argc == 2 && !NIL_P(vflags)) {
	    flags = NUM2UINT(vflags);
	}
    }
    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
	rb_sys_fail(0);
    if (pid == 0) {
	rb_last_status_clear();
	return Qnil;
    }
    return PIDT2NUM(pid);
}

.wait2(pid = -1, flags = 0) ⇒ Array .waitpid2(pid = -1, flags = 0) ⇒ Array

Waits for a child process to exit (see Process::waitpid for exact semantics) and returns an array containing the process id and the exit status (a Process::Status object) of that child. Raises a SystemCallError if there are no child processes.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

Overloads:

  • .wait2(pid = -1, flags = 0) ⇒ Array

    Returns:

  • .waitpid2(pid = -1, flags = 0) ⇒ Array

    Returns:


878
879
880
881
882
883
884
# File 'process.c', line 878

static VALUE
proc_wait2(int argc, VALUE *argv)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}

Instance Method Details

#daemon0 (private) #daemon(nochdir = nil, noclose = nil) ⇒ 0 (private)

Detach the process from controlling terminal and run in the background as system daemon. Unless the argument nochdir is true (i.e. non false), it changes the current working directory to the root ("/"). Unless the argument noclose is true, daemon() will redirect standard input, standard output and standard error to /dev/null. Return zero on success, or raise one of Errno::*.

Returns:

  • (0)
  • (0)

5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
# File 'process.c', line 5648

static VALUE
proc_daemon(int argc, VALUE *argv)
{
    VALUE nochdir, noclose;
    int n;

    rb_secure(2);
    rb_scan_args(argc, argv, "02", &nochdir, &noclose);

    prefork();
    n = rb_daemon(RTEST(nochdir), RTEST(noclose));
    if (n < 0) rb_sys_fail("daemon");
    return INT2FIX(n);
}

#detach(pid) ⇒ Object (private)

Some operating systems retain the status of terminated child processes until the parent collects that status (normally using some variant of wait(). If the parent never collects this status, the child stays around as a zombie process. Process::detach prevents this by setting up a separate Ruby thread whose sole job is to reap the status of the process pid when it terminates. Use detach only when you do not intent to explicitly wait for the child to terminate.

The waiting thread returns the exit status of the detached process when it terminates, so you can use Thread#join to know the result. If specified pid is not a valid child process ID, the thread returns nil immediately.

The waiting thread has pid method which returns the pid.

In this first example, we don't reap the first child process, so it appears as a zombie in the process status display.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

produces:

27389 Z

In the next example, Process::detach is used to reap the child automatically.

p1 = fork { sleep 0.1 }
p2 = fork { sleep 0.2 }
Process.detach(p1)
Process.waitpid(p2)
sleep 2
system("ps -ho pid,state -p #{p1}")

(produces no output)


1032
1033
1034
1035
1036
1037
# File 'process.c', line 1032

static VALUE
proc_detach(VALUE obj, VALUE pid)
{
    rb_secure(2);
    return rb_detach_process(NUM2PIDT(pid));
}

#egidFixnum (private) #Process::GID.eidFixnum (private) #Process::Sys.geteidFixnum (private)

Returns the effective group ID for this process. Not available on all platforms.

Process.egid   #=> 500

Returns:


6051
6052
6053
6054
6055
6056
6057
# File 'process.c', line 6051

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}

#egid=Object (private)

#euidFixnum (private) #Process::UID.eidFixnum (private) #Process::Sys.geteuidFixnum (private)

Returns the effective user ID for this process.

Process.euid   #=> 501

Returns:


5925
5926
5927
5928
5929
5930
# File 'process.c', line 5925

static VALUE
proc_geteuid(VALUE obj)
{
    rb_uid_t euid = geteuid();
    return UIDT2NUM(euid);
}

#euid=(user) ⇒ Object (private)

Sets the effective user ID for this process. Not available on all platforms.


5964
5965
5966
5967
5968
5969
5970
5971
# File 'process.c', line 5964

static VALUE
proc_seteuid_m(VALUE mod, VALUE euid)
{
    PREPARE_GETPWNAM;
    check_uid_switch();
    proc_seteuid(OBJ2UID(euid));
    return euid;
}

#getpgid(pid) ⇒ Integer (private)

Returns the process group ID for the given process id. Not available on all platforms.

Process.getpgid(Process.ppid())   #=> 25527

Returns:


4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
# File 'process.c', line 4187

static VALUE
proc_getpgid(VALUE obj, VALUE pid)
{
    rb_pid_t i;

    rb_secure(2);
    i = getpgid(NUM2PIDT(pid));
    if (i < 0) rb_sys_fail(0);
    return PIDT2NUM(i);
}

#getpgrpInteger (private)

Returns the process group ID for this process. Not available on all platforms.

Process.getpgid(0)   #=> 25527
Process.getpgrp      #=> 25527

Returns:


4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
# File 'process.c', line 4126

static VALUE
proc_getpgrp(void)
{
    rb_pid_t pgrp;

    rb_secure(2);
#if defined(HAVE_GETPGRP) && defined(GETPGRP_VOID)
    pgrp = getpgrp();
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#else /* defined(HAVE_GETPGID) */
    pgrp = getpgid(0);
    if (pgrp < 0) rb_sys_fail(0);
    return PIDT2NUM(pgrp);
#endif
}

#getpriority(kind, integer) ⇒ Fixnum (private)

Gets the scheduling priority for specified process, process group, or user. kind indicates the kind of entity to find: one of Process::PRIO_PGRP, Process::PRIO_USER, or Process::PRIO_PROCESS. integer is an id indicating the particular process, process group, or user (an id of 0 means current). Lower priorities are more favorable for scheduling. Not available on all platforms.

Process.getpriority(Process::PRIO_USER, 0)      #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)   #=> 19

Returns:


4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
# File 'process.c', line 4339

static VALUE
proc_getpriority(VALUE obj, VALUE which, VALUE who)
{
    int prio, iwhich, iwho;

    rb_secure(2);
    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);

    errno = 0;
    prio = getpriority(iwhich, iwho);
    if (errno) rb_sys_fail(0);
    return INT2FIX(prio);
}

#getrlimit(resource) ⇒ Array (private)

Gets the resource limit of the process. cur_limit means current (soft) limit and max_limit means maximum (hard) limit.

resource indicates the kind of resource to limit. It is specified as a symbol such as :CORE, a string such as "CORE" or a constant such as Process::RLIMIT_CORE. See Process.setrlimit for details.

cur_limit and max_limit may be Process::RLIM_INFINITY, Process::RLIM_SAVED_MAX or Process::RLIM_SAVED_CUR. See Process.setrlimit and the system getrlimit(2) manual for details.

Returns:


4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
# File 'process.c', line 4609

static VALUE
proc_getrlimit(VALUE obj, VALUE resource)
{
    struct rlimit rlim;

    rb_secure(2);

    if (getrlimit(rlimit_resource_type(resource), &rlim) < 0) {
	rb_sys_fail("getrlimit");
    }
    return rb_assoc_new(RLIM2NUM(rlim.rlim_cur), RLIM2NUM(rlim.rlim_max));
}

#getsidInteger (private) #getsid(pid) ⇒ Integer (private)

Returns the session ID for for the given process id. If not give, return current process sid. Not available on all platforms.

Process.getsid()                #=> 27422
Process.getsid(0)               #=> 27422
Process.getsid(Process.pid())   #=> 27422

Returns:


4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
# File 'process.c', line 4241

static VALUE
proc_getsid(int argc, VALUE *argv)
{
    rb_pid_t sid;
    VALUE pid;

    rb_secure(2);
    rb_scan_args(argc, argv, "01", &pid);

    if (NIL_P(pid))
	pid = INT2NUM(0);

    sid = getsid(NUM2PIDT(pid));
    if (sid < 0) rb_sys_fail(0);
    return PIDT2NUM(sid);
}

#gidFixnum (private) #Process::GID.ridFixnum (private) #Process::Sys.getgidFixnum (private)

Returns the (real) group ID for this process.

Process.gid   #=> 500

Returns:


5366
5367
5368
5369
5370
5371
# File 'process.c', line 5366

static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}

#gid=(fixnum) ⇒ Fixnum (private)

Sets the group ID for this process.

Returns:


5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
# File 'process.c', line 5382

static VALUE
proc_setgid(VALUE obj, VALUE id)
{
    rb_gid_t gid;
    PREPARE_GETGRNAM;

    check_gid_switch();

    gid = OBJ2GID(id);
#if defined(HAVE_SETRESGID)
    if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREGID
    if (setregid(gid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRGID
    if (setrgid(gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
    {
	if (getegid() == gid) {
	    if (setgid(gid) < 0) rb_sys_fail(0);
	}
	else {
	    rb_notimplement();
	}
    }
#endif
    return GIDT2NUM(gid);
}

#groupsArray (private)

Get an Array of the gids of groups in the supplemental group access list for this process.

Process.groups   #=> [27, 6, 10, 11]

Returns:


5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
# File 'process.c', line 5475

static VALUE
proc_getgroups(VALUE obj)
{
    VALUE ary;
    int i, ngroups;
    rb_gid_t *groups;

    ngroups = getgroups(0, NULL);
    if (ngroups == -1)
	rb_sys_fail(0);

    groups = ALLOCA_N(rb_gid_t, ngroups);

    ngroups = getgroups(ngroups, groups);
    if (ngroups == -1)
	rb_sys_fail(0);

    ary = rb_ary_new();
    for (i = 0; i < ngroups; i++)
	rb_ary_push(ary, GIDT2NUM(groups[i]));

    return ary;
}

#groups=(array) ⇒ Array (private)

Set the supplemental group access list to the given Array of group IDs.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.groups = [27, 6, 10, 11]   #=> [27, 6, 10, 11]
Process.groups   #=> [27, 6, 10, 11]

Returns:


5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
# File 'process.c', line 5517

static VALUE
proc_setgroups(VALUE obj, VALUE ary)
{
    int ngroups, i;
    rb_gid_t *groups;
    PREPARE_GETGRNAM;

    Check_Type(ary, T_ARRAY);

    ngroups = RARRAY_LENINT(ary);
    if (ngroups > maxgroups())
	rb_raise(rb_eArgError, "too many groups, %d max", maxgroups());

    groups = ALLOCA_N(rb_gid_t, ngroups);

    for (i = 0; i < ngroups; i++) {
	VALUE g = RARRAY_PTR(ary)[i];

	groups[i] = OBJ2GID(g);
    }

    if (setgroups(ngroups, groups) == -1) /* ngroups <= maxgroups */
	rb_sys_fail(0);

    return proc_getgroups(obj);
}

#initgroups(username, gid) ⇒ Array (private)

Initializes the supplemental group access list by reading the system group database and using all groups of which the given user is a member. The group with the specified gid is also added to the list. Returns the resulting Array of the gids of all the groups in the supplementary group access list. Not available on all platforms.

Process.groups   #=> [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
Process.initgroups( "mgranger", 30 )   #=> [30, 6, 10, 11]
Process.groups   #=> [30, 6, 10, 11]

Returns:


5566
5567
5568
5569
5570
5571
5572
5573
5574
# File 'process.c', line 5566

static VALUE
proc_initgroups(VALUE obj, VALUE uname, VALUE base_grp)
{
    PREPARE_GETGRNAM;
    if (initgroups(StringValuePtr(uname), OBJ2GID(base_grp)) != 0) {
	rb_sys_fail(0);
    }
    return proc_getgroups(obj);
}

#kill(signal, pid, ...) ⇒ Fixnum (private)

Sends the given signal to the specified process id(s) if pid is positive. If pid is zero signal is sent to all processes whose group ID is equal to the group ID of the process. signal may be an integer signal number or a POSIX signal name (either with or without a SIG prefix). If signal is negative (or starts with a minus sign), kills process groups instead of processes. Not all signals are available on all platforms.

pid = fork do
   Signal.trap("HUP") { puts "Ouch!"; exit }
   # ... do some work ...
end
# ...
Process.kill("HUP", pid)
Process.wait

produces:

Ouch!

If signal is an integer but wrong for signal, Errno::EINVAL or RangeError will be raised. Otherwise unless signal is a String or a Symbol, and a known signal name, ArgumentError will be raised.

Also, Errno::ESRCH or RangeError for invalid pid, Errno::EPERM when failed because of no privilege, will be raised. In these cases, signals may have been sent to preceding processes.

Returns:


363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'signal.c', line 363

VALUE
rb_f_kill(int argc, VALUE *argv)
{
#ifndef HAS_KILLPG
#define killpg(pg, sig) kill(-(pg), (sig))
#endif
    int negative = 0;
    int sig;
    int i;
    volatile VALUE str;
    const char *s;

    rb_secure(2);
    rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);

    switch (TYPE(argv[0])) {
      case T_FIXNUM:
	sig = FIX2INT(argv[0]);
	break;

      case T_SYMBOL:
	s = rb_id2name(SYM2ID(argv[0]));
	if (!s) rb_raise(rb_eArgError, "bad signal");
	goto str_signal;

      case T_STRING:
	s = RSTRING_PTR(argv[0]);
      str_signal:
	if (s[0] == '-') {
	    negative++;
	    s++;
	}
	if (strncmp("SIG", s, 3) == 0)
	    s += 3;
	if ((sig = signm2signo(s)) == 0)
	    rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);

	if (negative)
	    sig = -sig;
	break;

      default:
	str = rb_check_string_type(argv[0]);
	if (!NIL_P(str)) {
	    s = RSTRING_PTR(str);
	    goto str_signal;
	}
	rb_raise(rb_eArgError, "bad signal type %s",
		 rb_obj_classname(argv[0]));
	break;
    }

    if (sig < 0) {
	sig = -sig;
	for (i=1; i<argc; i++) {
	    if (killpg(NUM2PIDT(argv[i]), sig) < 0)
		rb_sys_fail(0);
	}
    }
    else {
	for (i=1; i<argc; i++) {
	    if (kill(NUM2PIDT(argv[i]), sig) < 0)
		rb_sys_fail(0);
	}
    }
    return INT2FIX(i-1);
}

#maxgroupsFixnum (private)

Returns the maximum number of gids allowed in the supplemental group access list.

Process.maxgroups   #=> 32

Returns:


5590
5591
5592
5593
5594
# File 'process.c', line 5590

static VALUE
proc_getmaxgroups(VALUE obj)
{
    return INT2FIX(maxgroups());
}

#maxgroups=(fixnum) ⇒ Fixnum (private)

Sets the maximum number of gids allowed in the supplemental group access list.

Returns:


5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
# File 'process.c', line 5608

static VALUE
proc_setmaxgroups(VALUE obj, VALUE val)
{
    int ngroups = FIX2INT(val);
    int ngroups_max = get_sc_ngroups_max();

    if (ngroups <= 0)
	rb_raise(rb_eArgError, "maxgroups %d shold be positive", ngroups);

    if (ngroups > RB_MAX_GROUPS)
	ngroups = RB_MAX_GROUPS;

    if (ngroups_max > 0 && ngroups > ngroups_max)
	ngroups = ngroups_max;

    _maxgroups = ngroups;

    return INT2FIX(_maxgroups);
}

#pidFixnum (private)

Returns the process id of this process. Not available on all platforms.

Process.pid   #=> 27415

Returns:


205
206
207
208
209
210
# File 'process.c', line 205

static VALUE
get_pid(void)
{
    rb_secure(2);
    return PIDT2NUM(getpid());
}

#ppidFixnum (private)

Returns the process id of the parent of this process. Returns untrustworthy value on Win32/64. Not available on all platforms.

puts "I am #{Process.pid}"
Process.fork { puts "Dad is #{Process.ppid}" }

produces:

I am 27417
Dad is 27417

Returns:


229
230
231
232
233
234
# File 'process.c', line 229

static VALUE
get_ppid(void)
{
    rb_secure(2);
    return PIDT2NUM(getppid());
}

#setpgid(pid, integer) ⇒ 0 (private)

Sets the process group ID of pid (0 indicates this process) to integer. Not available on all platforms.

Returns:

  • (0)

4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
# File 'process.c', line 4211

static VALUE
proc_setpgid(VALUE obj, VALUE pid, VALUE pgrp)
{
    rb_pid_t ipid, ipgrp;

    rb_secure(2);
    ipid = NUM2PIDT(pid);
    ipgrp = NUM2PIDT(pgrp);

    if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0);
    return INT2FIX(0);
}

#setpgrp0 (private)

Equivalent to setpgid(0,0). Not available on all platforms.

Returns:

  • (0)

4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
# File 'process.c', line 4156

static VALUE
proc_setpgrp(void)
{
    rb_secure(2);
  /* check for posix setpgid() first; this matches the posix */
  /* getpgrp() above.  It appears that configure will set SETPGRP_VOID */
  /* even though setpgrp(0,0) would be preferred. The posix call avoids */
  /* this confusion. */
#ifdef HAVE_SETPGID
    if (setpgid(0,0) < 0) rb_sys_fail(0);
#elif defined(HAVE_SETPGRP) && defined(SETPGRP_VOID)
    if (setpgrp() < 0) rb_sys_fail(0);
#endif
    return INT2FIX(0);
}

#setpriority(kind, integer, priority) ⇒ 0 (private)

See Process#getpriority.

Process.setpriority(Process::PRIO_USER, 0, 19)      #=> 0
Process.setpriority(Process::PRIO_PROCESS, 0, 19)   #=> 0
Process.getpriority(Process::PRIO_USER, 0)          #=> 19
Process.getpriority(Process::PRIO_PROCESS, 0)       #=> 19

Returns:

  • (0)

4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
# File 'process.c', line 4371

static VALUE
proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio)
{
    int iwhich, iwho, iprio;

    rb_secure(2);
    iwhich = NUM2INT(which);
    iwho   = NUM2INT(who);
    iprio  = NUM2INT(prio);

    if (setpriority(iwhich, iwho, iprio) < 0)
	rb_sys_fail(0);
    return INT2FIX(0);
}

#setrlimit(resource, cur_limit, max_limit) ⇒ nil (private) #setrlimit(resource, cur_limit) ⇒ nil (private)

Sets the resource limit of the process. cur_limit means current (soft) limit and max_limit means maximum (hard) limit.

If max_limit is not given, cur_limit is used.

resource indicates the kind of resource to limit. It should be a symbol such as :CORE, a string such as "CORE" or a constant such as Process::RLIMIT_CORE. The available resources are OS dependent. Ruby may support following resources.

AS

total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD but 4.4BSD-Lite)

CORE

core size (bytes) (SUSv3)

CPU

CPU time (seconds) (SUSv3)

DATA

data segment (bytes) (SUSv3)

FSIZE

file size (bytes) (SUSv3)

MEMLOCK

total size for mlock(2) (bytes) (4.4BSD, GNU/Linux)

MSGQUEUE

allocation for POSIX message queues (bytes) (GNU/Linux)

NICE

ceiling on process's nice(2) value (number) (GNU/Linux)

NOFILE

file descriptors (number) (SUSv3)

NPROC

number of processes for the user (number) (4.4BSD, GNU/Linux)

RSS

resident memory size (bytes) (4.2BSD, GNU/Linux)

RTPRIO

ceiling on the process's real-time priority (number) (GNU/Linux)

RTTIME

CPU time for real-time process (us) (GNU/Linux)

SBSIZE

all socket buffers (bytes) (NetBSD, FreeBSD)

SIGPENDING

number of queued signals allowed (signals) (GNU/Linux)

STACK

stack size (bytes) (SUSv3)

cur_limit and max_limit may be :INFINITY, "INFINITY" or Process::RLIM_INFINITY, which means that the resource is not limited. They may be Process::RLIM_SAVED_MAX, Process::RLIM_SAVED_CUR and corresponding symbols and strings too. See system setrlimit(2) manual for details.

The following example raises the soft limit of core size to the hard limit to try to make core dump possible.

Process.setrlimit(:CORE, Process.getrlimit(:CORE)[1])

Returns:

  • (nil)
  • (nil)

4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
# File 'process.c', line 4677

static VALUE
proc_setrlimit(int argc, VALUE *argv, VALUE obj)
{
    VALUE resource, rlim_cur, rlim_max;
    struct rlimit rlim;

    rb_secure(2);

    rb_scan_args(argc, argv, "21", &resource, &rlim_cur, &rlim_max);
    if (rlim_max == Qnil)
        rlim_max = rlim_cur;

    rlim.rlim_cur = rlimit_resource_value(rlim_cur);
    rlim.rlim_max = rlimit_resource_value(rlim_max);

    if (setrlimit(rlimit_resource_type(resource), &rlim) < 0) {
	rb_sys_fail("setrlimit");
    }
    return Qnil;
}

#setsidFixnum (private)

Establishes this process as a new session and process group leader, with no controlling tty. Returns the session id. Not available on all platforms.

Process.setsid   #=> 27422

Returns:


4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
# File 'process.c', line 4278

static VALUE
proc_setsid(void)
{
    rb_pid_t pid;

    rb_secure(2);
    pid = setsid();
    if (pid < 0) rb_sys_fail(0);
    return PIDT2NUM(pid);
}

#timesaStructTms (private)

Returns a Tms structure (see Struct::Tms) that contains user and system CPU times for this process, and also for children processes.

t = Process.times
[ t.utime, t.stime, t.cutime, t.cstime ]   #=> [0.0, 0.02, 0.00, 0.00]

Returns:

  • (aStructTms)

6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
# File 'process.c', line 6538

VALUE
rb_proc_times(VALUE obj)
{
    const double hertz =
#ifdef HAVE__SC_CLK_TCK
	(double)sysconf(_SC_CLK_TCK);
#else
#ifndef HZ
# ifdef CLK_TCK
#   define HZ CLK_TCK
# else
#   define HZ 60
# endif
#endif /* HZ */
	HZ;
#endif
    struct tms buf;
    volatile VALUE utime, stime, cutime, sctime;

    times(&buf);
    return rb_struct_new(rb_cProcessTms,
			 utime = DBL2NUM(buf.tms_utime / hertz),
			 stime = DBL2NUM(buf.tms_stime / hertz),
			 cutime = DBL2NUM(buf.tms_cutime / hertz),
			 sctime = DBL2NUM(buf.tms_cstime / hertz));
}

#uidFixnum (private) #Process::UID.ridFixnum (private) #Process::Sys.getuidFixnum (private)

Returns the (real) user ID of this process.

Process.uid   #=> 501

Returns:


4958
4959
4960
4961
4962
4963
# File 'process.c', line 4958

static VALUE
proc_getuid(VALUE obj)
{
    rb_uid_t uid = getuid();
    return UIDT2NUM(uid);
}

#uid=(user) ⇒ Numeric (private)

Sets the (user) user ID for this process. Not available on all platforms.

Returns:


4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
# File 'process.c', line 4975

static VALUE
proc_setuid(VALUE obj, VALUE id)
{
    rb_uid_t uid;
    PREPARE_GETPWNAM;

    check_uid_switch();

    uid = OBJ2UID(id);
#if defined(HAVE_SETRESUID)
    if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETREUID
    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
#elif defined HAVE_SETRUID
    if (setruid(uid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETUID
    {
	if (geteuid() == uid) {
	    if (setuid(uid) < 0) rb_sys_fail(0);
	}
	else {
	    rb_notimplement();
	}
    }
#endif
    return id;
}

#waitFixnum (private) #wait(pid = -1, flags = 0) ⇒ Fixnum (private) #waitpid(pid = -1, flags = 0) ⇒ Fixnum (private)

Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object containing information on that process. Which child it waits on depends on the value of pid:

> 0

Waits for the child whose process ID equals pid.

0

Waits for any child whose process group ID equals that of the calling process.

-1

Waits for any child process (the default if no pid is given).

< -1

Waits for any child whose process group ID equals the absolute value of pid.

The flags argument may be a logical or of the flag values Process::WNOHANG (do not block if no child available) or Process::WUNTRACED (return stopped children that haven't been reported). Not all flags are available on all platforms, but a flag value of zero will work on all platforms.

Calling this method raises a SystemCallError if there are no child processes. Not available on all platforms.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900

Returns:


833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# File 'process.c', line 833

static VALUE
proc_wait(int argc, VALUE *argv)
{
    VALUE vpid, vflags;
    rb_pid_t pid;
    int flags, status;

    rb_secure(2);
    flags = 0;
    if (argc == 0) {
	pid = -1;
    }
    else {
	rb_scan_args(argc, argv, "02", &vpid, &vflags);
	pid = NUM2PIDT(vpid);
	if (argc == 2 && !NIL_P(vflags)) {
	    flags = NUM2UINT(vflags);
	}
    }
    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
	rb_sys_fail(0);
    if (pid == 0) {
	rb_last_status_clear();
	return Qnil;
    }
    return PIDT2NUM(pid);
}

#wait2(pid = -1, flags = 0) ⇒ Array (private) #waitpid2(pid = -1, flags = 0) ⇒ Array (private)

Waits for a child process to exit (see Process::waitpid for exact semantics) and returns an array containing the process id and the exit status (a Process::Status object) of that child. Raises a SystemCallError if there are no child processes.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

Returns:


878
879
880
881
882
883
884
# File 'process.c', line 878

static VALUE
proc_wait2(int argc, VALUE *argv)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}

#waitallArray (private)

Waits for all children, returning an array of pid/status pairs (where status is a Process::Status object).

fork { sleep 0.2; exit 2 }   #=> 27432
fork { sleep 0.1; exit 1 }   #=> 27433
fork {            exit 0 }   #=> 27434
p Process.waitall

produces:

[[30982, #<Process::Status: pid 30982 exit 0>],
 [30979, #<Process::Status: pid 30979 exit 1>],
 [30976, #<Process::Status: pid 30976 exit 2>]]

Returns:


907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
# File 'process.c', line 907

static VALUE
proc_waitall(void)
{
    VALUE result;
    rb_pid_t pid;
    int status;

    rb_secure(2);
    result = rb_ary_new();
#ifdef NO_WAITPID
    if (pid_tbl) {
	st_foreach(pid_tbl, waitall_each, result);
    }
#else
    rb_last_status_clear();
#endif

    for (pid = -1;;) {
#ifdef NO_WAITPID
	pid = wait(&status);
#else
	pid = rb_waitpid(-1, &status, 0);
#endif
	if (pid == -1) {
	    if (errno == ECHILD)
		break;
#ifdef NO_WAITPID
	    if (errno == EINTR) {
		rb_thread_schedule();
		continue;
	    }
#endif
	    rb_sys_fail(0);
	}
#ifdef NO_WAITPID
	rb_last_status_set(status, pid);
#endif
	rb_ary_push(result, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get()));
    }
    return result;
}

#waitFixnum (private) #wait(pid = -1, flags = 0) ⇒ Fixnum (private) #waitpid(pid = -1, flags = 0) ⇒ Fixnum (private)

Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object containing information on that process. Which child it waits on depends on the value of pid:

> 0

Waits for the child whose process ID equals pid.

0

Waits for any child whose process group ID equals that of the calling process.

-1

Waits for any child process (the default if no pid is given).

< -1

Waits for any child whose process group ID equals the absolute value of pid.

The flags argument may be a logical or of the flag values Process::WNOHANG (do not block if no child available) or Process::WUNTRACED (return stopped children that haven't been reported). Not all flags are available on all platforms, but a flag value of zero will work on all platforms.

Calling this method raises a SystemCallError if there are no child processes. Not available on all platforms.

include Process
fork { exit 99 }                 #=> 27429
wait                             #=> 27429
$?.exitstatus                    #=> 99

pid = fork { sleep 3 }           #=> 27440
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, Process::WNOHANG)   #=> nil
Time.now                         #=> 2008-03-08 19:56:16 +0900
waitpid(pid, 0)                  #=> 27440
Time.now                         #=> 2008-03-08 19:56:19 +0900

Returns:


833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
# File 'process.c', line 833

static VALUE
proc_wait(int argc, VALUE *argv)
{
    VALUE vpid, vflags;
    rb_pid_t pid;
    int flags, status;

    rb_secure(2);
    flags = 0;
    if (argc == 0) {
	pid = -1;
    }
    else {
	rb_scan_args(argc, argv, "02", &vpid, &vflags);
	pid = NUM2PIDT(vpid);
	if (argc == 2 && !NIL_P(vflags)) {
	    flags = NUM2UINT(vflags);
	}
    }
    if ((pid = rb_waitpid(pid, &status, flags)) < 0)
	rb_sys_fail(0);
    if (pid == 0) {
	rb_last_status_clear();
	return Qnil;
    }
    return PIDT2NUM(pid);
}

#wait2(pid = -1, flags = 0) ⇒ Array (private) #waitpid2(pid = -1, flags = 0) ⇒ Array (private)

Waits for a child process to exit (see Process::waitpid for exact semantics) and returns an array containing the process id and the exit status (a Process::Status object) of that child. Raises a SystemCallError if there are no child processes.

Process.fork { exit 99 }   #=> 27437
pid, status = Process.wait2
pid                        #=> 27437
status.exitstatus          #=> 99

Returns:


878
879
880
881
882
883
884
# File 'process.c', line 878

static VALUE
proc_wait2(int argc, VALUE *argv)
{
    VALUE pid = proc_wait(argc, argv);
    if (NIL_P(pid)) return Qnil;
    return rb_assoc_new(pid, rb_last_status_get());
}