# <!-- rdoc-file=process.c -->
# Module `Process` represents a process in the underlying operating system. Its
# methods support management of the current process and its child processes.
#
# ## Process Creation
#
# Each of the following methods executes a given command in a new process or
# subshell, or multiple commands in new processes and/or subshells. The choice
# of process or subshell depends on the form of the command; see [Argument
# command_line or exe_path](rdoc-ref:Process@Argument+command_line+or+exe_path).
#
# *   Process.spawn, Kernel#spawn: Executes the command; returns the new pid
#     without waiting for completion.
# *   Process.exec: Replaces the current process by executing the command.
#
#
# In addition:
#
# *   Method Kernel#system executes a given command-line (string) in a subshell;
#     returns `true`, `false`, or `nil`.
# *   Method Kernel#` executes a given command-line (string) in a subshell;
#     returns its $stdout string.
# *   Module Open3 supports creating child processes with access to their
#     $stdin, $stdout, and $stderr streams.
#
#
# ### Execution Environment
#
# Optional leading argument `env` is a hash of name/value pairs, where each name
# is a string and each value is a string or `nil`; each name/value pair is added
# to ENV in the new process.
#
#     Process.spawn(                'ruby -e "p ENV[\"Foo\"]"')
#     Process.spawn({'Foo' => '0'}, 'ruby -e "p ENV[\"Foo\"]"')
#
# Output:
#
#     "0"
#
# The effect is usually similar to that of calling ENV#update with argument
# `env`, where each named environment variable is created or updated (if the
# value is non-`nil`), or deleted (if the value is `nil`).
#
# However, some modifications to the calling process may remain if the new
# process fails. For example, hard resource limits are not restored.
#
# ### Argument `command_line` or `exe_path`
#
# The required string argument is one of the following:
#
# *   `command_line` if it begins with a shell reserved word or special
#     built-in, or if it contains one or more meta characters.
# *   `exe_path` otherwise.
#
#
# **Argument `command_line`**
#
# String argument `command_line` is a command line to be passed to a shell; it
# must begin with a shell reserved word, begin with a special built-in, or
# contain meta characters:
#
#     system('if true; then echo "Foo"; fi')          # => true  # Shell reserved word.
#     system('echo')                                  # => true  # Built-in.
#     system('date > /tmp/date.tmp')                  # => true  # Contains meta character.
#     system('date > /nop/date.tmp')                  # => false
#     system('date > /nop/date.tmp', exception: true) # Raises RuntimeError.
#
# The command line may also contain arguments and options for the command:
#
#     system('echo "Foo"') # => true
#
# Output:
#
#     Foo
#
# See [Execution Shell](rdoc-ref:Process@Execution+Shell) for details about the
# shell.
#
# **Argument `exe_path`**
#
# Argument `exe_path` is one of the following:
#
# *   The string path to an executable to be called.
# *   A 2-element array containing the path to an executable to be called, and
#     the string to be used as the name of the executing process.
#
#
# Example:
#
#     system('/usr/bin/date') # => true # Path to date on Unix-style system.
#     system('foo')           # => nil  # Command failed.
#
# Output:
#
#     Mon Aug 28 11:43:10 AM CDT 2023
#
# ### Execution Options
#
# Optional trailing argument `options` is a hash of execution options.
#
# #### Working Directory (`:chdir`)
#
# By default, the working directory for the new process is the same as that of
# the current process:
#
#     Dir.chdir('/var')
#     Process.spawn('ruby -e "puts Dir.pwd"')
#
# Output:
#
#     /var
#
# Use option `:chdir` to set the working directory for the new process:
#
#     Process.spawn('ruby -e "puts Dir.pwd"', {chdir: '/tmp'})
#
# Output:
#
#     /tmp
#
# The working directory of the current process is not changed:
#
#     Dir.pwd # => "/var"
#
# #### File Redirection (File Descriptor)
#
# Use execution options for file redirection in the new process.
#
# The key for such an option may be an integer file descriptor (fd), specifying
# a source, or an array of fds, specifying multiple sources.
#
# An integer source fd may be specified as:
#
# *   *n*: Specifies file descriptor *n*.
#
#
# There are these shorthand symbols for fds:
#
# *   `:in`: Specifies file descriptor 0 (STDIN).
# *   `:out`: Specifies file descriptor 1 (STDOUT).
# *   `:err`: Specifies file descriptor 2 (STDERR).
#
#
# The value given with a source is one of:
#
# *   *n*: Redirects to fd *n* in the parent process.
# *   `filepath`: Redirects from or to the file at `filepath` via
#     `open(filepath, mode, 0644)`, where `mode` is `'r'` for source `:in`, or
#     `'w'` for source `:out` or `:err`.
# *   `[filepath]`: Redirects from the file at `filepath` via `open(filepath,
#     'r', 0644)`.
# *   `[filepath, mode]`: Redirects from or to the file at `filepath` via
#     `open(filepath, mode, 0644)`.
# *   `[filepath, mode, perm]`: Redirects from or to the file at `filepath` via
#     `open(filepath, mode, perm)`.
# *   `[:child, fd]`: Redirects to the redirected `fd`.
# *   `:close`: Closes the file descriptor in child process.
#
#
# See [Access Modes](rdoc-ref:File@Access+Modes) and [File
# Permissions](rdoc-ref:File@File+Permissions).
#
# #### Environment Variables (`:unsetenv_others`)
#
# By default, the new process inherits environment variables from the parent
# process; use execution option key `:unsetenv_others` with value `true` to
# clear environment variables in the new process.
#
# Any changes specified by execution option `env` are made after the new process
# inherits or clears its environment variables; see [Execution
# Environment](rdoc-ref:Process@Execution+Environment).
#
# #### File-Creation Access (`:umask`)
#
# Use execution option `:umask` to set the file-creation access for the new
# process; see [Access Modes](rdoc-ref:File@Access+Modes):
#
#     command = 'ruby -e "puts sprintf(\"0%o\", File.umask)"'
#     options = {:umask => 0644}
#     Process.spawn(command, options)
#
# Output:
#
#     0644
#
# #### Process Groups (`:pgroup` and `:new_pgroup`)
#
# By default, the new process belongs to the same [process
# group](https://en.wikipedia.org/wiki/Process_group) as the parent process.
#
# To specify a different process group. use execution option `:pgroup` with one
# of the following values:
#
# *   `true`: Create a new process group for the new process.
# *   *pgid*: Create the new process in the process group whose id is *pgid*.
#
#
# On Windows only, use execution option `:new_pgroup` with value `true` to
# create a new process group for the new process.
#
# #### Resource Limits
#
# Use execution options to set resource limits.
#
# The keys for these options are symbols of the form `:rlimit_*resource_name`*,
# where *resource_name* is the downcased form of one of the string resource
# names described at method Process.setrlimit. For example, key `:rlimit_cpu`
# corresponds to resource limit `'CPU'`.
#
# The value for such as key is one of:
#
# *   An integer, specifying both the current and maximum limits.
# *   A 2-element array of integers, specifying the current and maximum limits.
#
#
# #### File Descriptor Inheritance
#
# By default, the new process inherits file descriptors from the parent process.
#
# Use execution option `:close_others => true` to modify that inheritance by
# closing non-standard fds (3 and greater) that are not otherwise redirected.
#
# ### Execution Shell
#
# On a Unix-like system, the shell invoked is `/bin/sh`; otherwise the shell
# invoked is determined by environment variable `ENV['RUBYSHELL']`, if defined,
# or `ENV['COMSPEC']` otherwise.
#
# Except for the `COMSPEC` case, the entire string `command_line` is passed as
# an argument to [shell option
# -c](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh.
# html).
#
# The shell performs normal shell expansion on the command line:
#
#     spawn('echo C*') # => 799139
#     Process.wait     # => 799139
#
# Output:
#
#     CONTRIBUTING.md COPYING COPYING.ja
#
# ## What's Here
#
# ### Current-Process Getters
#
# *   ::argv0: Returns the process name as a frozen string.
# *   ::egid: Returns the effective group ID.
# *   ::euid: Returns the effective user ID.
# *   ::getpgrp: Return the process group ID.
# *   ::getrlimit: Returns the resource limit.
# *   ::gid: Returns the (real) group ID.
# *   ::pid: Returns the process ID.
# *   ::ppid: Returns the process ID of the parent process.
# *   ::uid: Returns the (real) user ID.
#
#
# ### Current-Process Setters
#
# *   ::egid=: Sets the effective group ID.
# *   ::euid=: Sets the effective user ID.
# *   ::gid=: Sets the (real) group ID.
# *   ::setproctitle: Sets the process title.
# *   ::setpgrp: Sets the process group ID of the process to zero.
# *   ::setrlimit: Sets a resource limit.
# *   ::setsid: Establishes the process as a new session and process group
#     leader, with no controlling tty.
# *   ::uid=: Sets the user ID.
#
#
# ### Current-Process Execution
#
# *   ::abort: Immediately terminates the process.
# *   ::daemon: Detaches the process from its controlling terminal and continues
#     running it in the background as system daemon.
# *   ::exec: Replaces the process by running a given external command.
# *   ::exit: Initiates process termination by raising exception SystemExit
#     (which may be caught).
# *   ::exit!: Immediately exits the process.
# *   ::warmup: Notifies the Ruby virtual machine that the boot sequence for the
#     application is completed, and that the VM may begin optimizing the
#     application.
#
#
# ### Child Processes
#
# *   ::detach: Guards against a child process becoming a zombie.
# *   ::fork: Creates a child process.
# *   ::kill: Sends a given signal to processes.
# *   ::spawn: Creates a child process.
# *   ::wait, ::waitpid: Waits for a child process to exit; returns its process
#     ID.
# *   ::wait2, ::waitpid2: Waits for a child process to exit; returns its
#     process ID and status.
# *   ::waitall: Waits for all child processes to exit; returns their process
#     IDs and statuses.
#
#
# ### Process Groups
#
# *   ::getpgid: Returns the process group ID for a process.
# *   ::getpriority: Returns the scheduling priority for a process, process
#     group, or user.
# *   ::getsid: Returns the session ID for a process.
# *   ::groups: Returns an array of the group IDs in the supplemental group
#     access list for this process.
# *   ::groups=: Sets the supplemental group access list to the given array of
#     group IDs.
# *   ::initgroups: Initializes the supplemental group access list.
# *   ::last_status: Returns the status of the last executed child process in
#     the current thread.
# *   ::maxgroups: Returns the maximum number of group IDs allowed in the
#     supplemental group access list.
# *   ::maxgroups=: Sets the maximum number of group IDs allowed in the
#     supplemental group access list.
# *   ::setpgid: Sets the process group ID of a process.
# *   ::setpriority: Sets the scheduling priority for a process, process group,
#     or user.
#
#
# ### Timing
#
# *   ::clock_getres: Returns the resolution of a system clock.
# *   ::clock_gettime: Returns the time from a system clock.
# *   ::times: Returns a Process::Tms object containing times for the current
#     process and its child processes.
#
module Process
  # <!--
  #   rdoc-file=process.c
  #   - Process._fork   -> integer
  # -->
  # An internal API for fork. Do not call this method directly. Currently, this is
  # called via Kernel#fork, Process.fork, and IO.popen with `"-"`.
  #
  # This method is not for casual code but for application monitoring libraries.
  # You can add custom code before and after fork events by overriding this
  # method.
  #
  # Note: Process.daemon may be implemented using fork(2) BUT does not go through
  # this method. Thus, depending on your reason to hook into this method, you may
  # also want to hook into that one. See [this
  # issue](https://bugs.ruby-lang.org/issues/18911) for a more detailed discussion
  # of this.
  #
  def self._fork: () -> Integer

  # <!--
  #   rdoc-file=ruby.c
  #   - Process.argv0  -> frozen_string
  # -->
  # Returns the name of the script being executed.  The value is not affected by
  # assigning a new value to $0.
  #
  # This method first appeared in Ruby 2.1 to serve as a global variable free
  # means to get the script name.
  #
  def self.argv0: () -> String

  # <!--
  #   rdoc-file=process.c
  #   - Process.clock_getres(clock_id, unit = :float_second)  -> number
  # -->
  # Returns a clock resolution as determined by POSIX function
  # [clock_getres()](https://man7.org/linux/man-pages/man3/clock_getres.3.html):
  #
  #     Process.clock_getres(:CLOCK_REALTIME) # => 1.0e-09
  #
  # See Process.clock_gettime for the values of `clock_id` and `unit`.
  #
  # Examples:
  #
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_microsecond) # => 0.001
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_millisecond) # => 1.0e-06
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :float_second)      # => 1.0e-09
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :microsecond)       # => 0
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :millisecond)       # => 0
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond)        # => 1
  #     Process.clock_getres(:CLOCK_PROCESS_CPUTIME_ID, :second)            # => 0
  #
  # In addition to the values for `unit` supported in Process.clock_gettime, this
  # method supports `:hertz`, the integer number of clock ticks per second (which
  # is the reciprocal of `:float_second`):
  #
  #     Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)        # => 100.0
  #     Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :float_second) # => 0.01
  #
  # **Accuracy**: Note that the returned resolution may be inaccurate on some
  # platforms due to underlying bugs. Inaccurate resolutions have been reported
  # for various clocks including `:CLOCK_MONOTONIC` and `:CLOCK_MONOTONIC_RAW` on
  # Linux, macOS, BSD or AIX platforms, when using ARM processors, or when using
  # virtualization.
  #
  def self.clock_getres: (Symbol | Integer clock_id, ?Symbol unit) -> (Float | Integer)

  # <!--
  #   rdoc-file=process.c
  #   - Process.clock_gettime(clock_id, unit = :float_second) -> number
  # -->
  # Returns a clock time as determined by POSIX function
  # [clock_gettime()](https://man7.org/linux/man-pages/man3/clock_gettime.3.html):
  #
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID) # => 198.650379677
  #
  # Argument `clock_id` should be a symbol or a constant that specifies the clock
  # whose time is to be returned; see below.
  #
  # Optional argument `unit` should be a symbol that specifies the unit to be used
  # in the returned clock time; see below.
  #
  # **Argument `clock_id`**
  #
  # Argument `clock_id` specifies the clock whose time is to be returned; it may
  # be a constant such as `Process::CLOCK_REALTIME`, or a symbol shorthand such as
  # `:CLOCK_REALTIME`.
  #
  # The supported clocks depend on the underlying operating system; this method
  # supports the following clocks on the indicated platforms (raises Errno::EINVAL
  # if called with an unsupported clock):
  #
  # *   `:CLOCK_BOOTTIME`: Linux 2.6.39.
  # *   `:CLOCK_BOOTTIME_ALARM`: Linux 3.0.
  # *   `:CLOCK_MONOTONIC`: SUSv3 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0,
  #     OpenBSD 3.4, macOS 10.12, Windows-2000.
  # *   `:CLOCK_MONOTONIC_COARSE`: Linux 2.6.32.
  # *   `:CLOCK_MONOTONIC_FAST`: FreeBSD 8.1.
  # *   `:CLOCK_MONOTONIC_PRECISE`: FreeBSD 8.1.
  # *   `:CLOCK_MONOTONIC_RAW`: Linux 2.6.28, macOS 10.12.
  # *   `:CLOCK_MONOTONIC_RAW_APPROX`: macOS 10.12.
  # *   `:CLOCK_PROCESS_CPUTIME_ID`: SUSv3 to 4, Linux 2.5.63, FreeBSD 9.3,
  #     OpenBSD 5.4, macOS 10.12.
  # *   `:CLOCK_PROF`: FreeBSD 3.0, OpenBSD 2.1.
  # *   `:CLOCK_REALTIME`: SUSv2 to 4, Linux 2.5.63, FreeBSD 3.0, NetBSD 2.0,
  #     OpenBSD 2.1, macOS 10.12, Windows-8/Server-2012. Time.now is recommended
  #     over +:CLOCK_REALTIME:.
  # *   `:CLOCK_REALTIME_ALARM`: Linux 3.0.
  # *   `:CLOCK_REALTIME_COARSE`: Linux 2.6.32.
  # *   `:CLOCK_REALTIME_FAST`: FreeBSD 8.1.
  # *   `:CLOCK_REALTIME_PRECISE`: FreeBSD 8.1.
  # *   `:CLOCK_SECOND`: FreeBSD 8.1.
  # *   `:CLOCK_TAI`: Linux 3.10.
  # *   `:CLOCK_THREAD_CPUTIME_ID`: SUSv3 to 4, Linux 2.5.63, FreeBSD 7.1, OpenBSD
  #     5.4, macOS 10.12.
  # *   `:CLOCK_UPTIME`: FreeBSD 7.0, OpenBSD 5.5.
  # *   `:CLOCK_UPTIME_FAST`: FreeBSD 8.1.
  # *   `:CLOCK_UPTIME_PRECISE`: FreeBSD 8.1.
  # *   `:CLOCK_UPTIME_RAW`: macOS 10.12.
  # *   `:CLOCK_UPTIME_RAW_APPROX`: macOS 10.12.
  # *   `:CLOCK_VIRTUAL`: FreeBSD 3.0, OpenBSD 2.1.
  #
  #
  # Note that SUS stands for Single Unix Specification. SUS contains POSIX and
  # clock_gettime is defined in the POSIX part. SUS defines `:CLOCK_REALTIME` as
  # mandatory but `:CLOCK_MONOTONIC`, `:CLOCK_PROCESS_CPUTIME_ID`, and
  # `:CLOCK_THREAD_CPUTIME_ID` are optional.
  #
  # Certain emulations are used when the given `clock_id` is not supported
  # directly:
  #
  # *   Emulations for `:CLOCK_REALTIME`:
  #
  #     *   `:GETTIMEOFDAY_BASED_CLOCK_REALTIME`: Use gettimeofday() defined by
  #         SUS (deprecated in SUSv4). The resolution is 1 microsecond.
  #     *   `:TIME_BASED_CLOCK_REALTIME`: Use time() defined by ISO C. The
  #         resolution is 1 second.
  #
  #
  # *   Emulations for `:CLOCK_MONOTONIC`:
  #
  #     *   `:MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC`: Use mach_absolute_time(),
  #         available on Darwin. The resolution is CPU dependent.
  #     *   `:TIMES_BASED_CLOCK_MONOTONIC`: Use the result value of times()
  #         defined by POSIX, thus:
  # > Upon successful completion, times() shall return the elapsed real
  #           time, in clock ticks, since an arbitrary point in the past (for
  #           example, system start-up time).
  #
  # > For example, GNU/Linux returns a value based on jiffies and it is
  #         monotonic. However, 4.4BSD uses gettimeofday() and it is not
  #         monotonic. (FreeBSD uses `:CLOCK_MONOTONIC` instead, though.)
  #
  #         The resolution is the clock tick. "getconf CLK_TCK" command shows the
  #         clock ticks per second. (The clock ticks-per-second is defined by HZ
  #         macro in older systems.) If it is 100 and clock_t is 32 bits integer
  #         type, the resolution is 10 millisecond and cannot represent over 497
  #         days.
  #
  #
  # *   Emulations for `:CLOCK_PROCESS_CPUTIME_ID`:
  #
  #     *   `:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID`: Use getrusage() defined
  #         by SUS. getrusage() is used with RUSAGE_SELF to obtain the time only
  #         for the calling process (excluding the time for child processes). The
  #         result is addition of user time (ru_utime) and system time (ru_stime).
  #         The resolution is 1 microsecond.
  #     *   `:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID`: Use times() defined by POSIX.
  #         The result is addition of user time (tms_utime) and system time
  #         (tms_stime). tms_cutime and tms_cstime are ignored to exclude the time
  #         for child processes. The resolution is the clock tick. "getconf
  #         CLK_TCK" command shows the clock ticks per second. (The clock ticks
  #         per second is defined by HZ macro in older systems.) If it is 100, the
  #         resolution is 10 millisecond.
  #     *   `:CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID`: Use clock() defined by ISO C.
  #         The resolution is `1/CLOCKS_PER_SEC`. `CLOCKS_PER_SEC` is the C-level
  #         macro defined by time.h. SUS defines `CLOCKS_PER_SEC` as 1000000;
  #         other systems may define it differently. If `CLOCKS_PER_SEC` is
  #         1000000 (as in SUS), the resolution is 1 microsecond. If
  #         `CLOCKS_PER_SEC` is 1000000 and clock_t is a 32-bit integer type, it
  #         cannot represent over 72 minutes.
  #
  #
  #
  # **Argument `unit`**
  #
  # Optional argument `unit` (default `:float_second`) specifies the unit for the
  # returned value.
  #
  # *   `:float_microsecond`: Number of microseconds as a float.
  # *   `:float_millisecond`: Number of milliseconds as a float.
  # *   `:float_second`: Number of seconds as a float.
  # *   `:microsecond`: Number of microseconds as an integer.
  # *   `:millisecond`: Number of milliseconds as an integer.
  # *   `:nanosecond`: Number of nanoseconds as an integer.
  # *   `::second`: Number of seconds as an integer.
  #
  #
  # Examples:
  #
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_microsecond)
  #     # => 203605054.825
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_millisecond)
  #     # => 203643.696848
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :float_second)
  #     # => 203.762181929
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :microsecond)
  #     # => 204123212
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :millisecond)
  #     # => 204298
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :nanosecond)
  #     # => 204602286036
  #     Process.clock_gettime(:CLOCK_PROCESS_CPUTIME_ID, :second)
  #     # => 204
  #
  # The underlying function, clock_gettime(), returns a number of nanoseconds.
  # Float object (IEEE 754 double) is not enough to represent the return value for
  # `:CLOCK_REALTIME`. If the exact nanoseconds value is required, use
  # `:nanosecond` as the `unit`.
  #
  # The origin (time zero) of the returned value is system-dependent, and may be,
  # for example, system start up time, process start up time, the Epoch, etc.
  #
  # The origin in `:CLOCK_REALTIME` is defined as the Epoch: `1970-01-01 00:00:00
  # UTC`; some systems count leap seconds and others don't, so the result may vary
  # across systems.
  #
  def self.clock_gettime: (Symbol | Integer clock_id) -> Float
                        | (Symbol | Integer clock_id, :float_second | :float_millisecond | :float_microsecond unit) -> Float
                        | (Symbol | Integer clock_id, :second | :millisecond | :microsecond | :nanosecond unit) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.daemon(nochdir = nil, noclose = nil) -> 0
  # -->
  # Detaches the current process from its controlling terminal and runs it in the
  # background as system daemon; returns zero.
  #
  # By default:
  #
  # *   Changes the current working directory to the root directory.
  # *   Redirects $stdin, $stdout, and $stderr to the null device.
  #
  #
  # If optional argument `nochdir` is `true`, does not change the current working
  # directory.
  #
  # If optional argument `noclose` is `true`, does not redirect $stdin, $stdout,
  # or $stderr.
  #
  def self.daemon: (?untyped nochdir, ?untyped noclose) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.detach(pid) -> thread
  # -->
  # Avoids the potential for a child process to become a [zombie
  # process](https://en.wikipedia.org/wiki/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.
  #
  # This method is needed only when the parent process will never wait for the
  # child process.
  #
  # This example does not reap the second child process; that process appears as a
  # zombie in the process status (`ps`) output:
  #
  #     pid = Process.spawn('ruby', '-e', 'exit 13') # => 312691
  #     sleep(1)
  #     # Find zombies.
  #     system("ps -ho pid,state -p #{pid}")
  #
  # Output:
  #
  #     312716 Z
  #
  # This example also does not reap the second child process, but it does detach
  # the process so that it does not become a zombie:
  #
  #     pid = Process.spawn('ruby', '-e', 'exit 13') # => 313213
  #     thread = Process.detach(pid)
  #     sleep(1)
  #     # => #<Process::Waiter:0x00007f038f48b838 run>
  #     system("ps -ho pid,state -p #{pid}")        # Finds no zombies.
  #
  # The waiting thread can return the pid of the detached child process:
  #
  #     thread.join.pid                       # => 313262
  #
  def self.detach: (Integer pid) -> Thread

  # <!--
  #   rdoc-file=process.c
  #   - Process.egid        -> integer
  #   - Process::GID.eid    -> integer
  #   - Process::Sys.geteid -> integer
  # -->
  # Returns the effective group ID for the current process:
  #
  #     Process.egid # => 500
  #
  # Not available on all platforms.
  #
  def self.egid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.egid = new_egid -> new_egid
  # -->
  # Sets the effective group ID for the current process.
  #
  # Not available on all platforms.
  #
  def self.egid=: (Integer arg0) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.euid         -> integer
  #   - Process::UID.eid     -> integer
  #   - Process::Sys.geteuid -> integer
  # -->
  # Returns the effective user ID for the current process.
  #
  #     Process.euid # => 501
  #
  def self.euid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.euid = new_euid -> new_euid
  # -->
  # Sets the effective user ID for the current process.
  #
  # Not available on all platforms.
  #
  def self.euid=: (Integer arg0) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.getpgid(pid) -> integer
  # -->
  # Returns the process group ID for the given process ID +pid+:
  #
  #       Process.getpgid(Process.ppid) # => 25527
  #
  # Not available on all platforms.
  #
  def self.getpgid: (Integer pid) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.getpgrp -> integer
  # -->
  # Returns the process group ID for the current process:
  #
  #     Process.getpgid(0) # => 25527
  #     Process.getpgrp    # => 25527
  #
  def self.getpgrp: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.getpriority(kind, id)   -> integer
  # -->
  # Returns the scheduling priority for specified process, process group, or user.
  #
  # Argument `kind` is one of:
  #
  # *   Process::PRIO_PROCESS: return priority for process.
  # *   Process::PRIO_PGRP: return priority for process group.
  # *   Process::PRIO_USER: return priority for user.
  #
  #
  # Argument `id` is the ID for the process, process group, or user; zero
  # specified the current ID for `kind`.
  #
  # Examples:
  #
  #     Process.getpriority(Process::PRIO_USER, 0)    # => 19
  #     Process.getpriority(Process::PRIO_PROCESS, 0) # => 19
  #
  # Not available on all platforms.
  #
  def self.getpriority: (Integer kind, Integer arg0) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.getrlimit(resource) -> [cur_limit, max_limit]
  # -->
  # Returns a 2-element array of the current (soft) limit and maximum (hard) limit
  # for the given `resource`.
  #
  # Argument `resource` specifies the resource whose limits are to be returned;
  # see Process.setrlimit.
  #
  # Each of the returned values `cur_limit` and `max_limit` is an integer; see
  # Process.setrlimit.
  #
  # Example:
  #
  #     Process.getrlimit(:CORE) # => [0, 18446744073709551615]
  #
  # See Process.setrlimit.
  #
  # Not available on all platforms.
  #
  def self.getrlimit: (interned | Integer resource) -> [ Integer, Integer ]

  # <!--
  #   rdoc-file=process.c
  #   - Process.getsid(pid = nil) -> integer
  # -->
  # Returns the session ID of the given process ID `pid`, or of the current
  # process if not given:
  #
  #     Process.getsid                # => 27422
  #     Process.getsid(0)             # => 27422
  #     Process.getsid(Process.pid()) # => 27422
  #
  # Not available on all platforms.
  #
  def self.getsid: (?Integer pid) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.gid         -> integer
  #   - Process::GID.rid    -> integer
  #   - Process::Sys.getgid -> integer
  # -->
  # Returns the (real) group ID for the current process:
  #
  #     Process.gid # => 1000
  #
  def self.gid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.gid = new_gid -> new_gid
  # -->
  # Sets the group ID for the current process to `new_gid`:
  #
  #     Process.gid = 1000 # => 1000
  #
  def self.gid=: (Integer arg0) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.groups -> array
  # -->
  # Returns an array of the group IDs in the supplemental group access list for
  # the current process:
  #
  #     Process.groups # => [4, 24, 27, 30, 46, 122, 135, 136, 1000]
  #
  # These properties of the returned array are system-dependent:
  #
  # *   Whether (and how) the array is sorted.
  # *   Whether the array includes effective group IDs.
  # *   Whether the array includes duplicate group IDs.
  # *   Whether the array size exceeds the value of Process.maxgroups.
  #
  #
  # Use this call to get a sorted and unique array:
  #
  #     Process.groups.uniq.sort
  #
  def self.groups: () -> ::Array[Integer]

  # <!--
  #   rdoc-file=process.c
  #   - Process.groups = new_groups -> new_groups
  # -->
  # Sets 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]
  #
  def self.groups=: (::Array[Integer] arg0) -> ::Array[Integer]

  # <!--
  #   rdoc-file=process.c
  #   - Process.initgroups(username, gid) -> array
  # -->
  # Sets the supplemental group access list; the new list includes:
  #
  # *   The group IDs of those groups to which the user given by `username`
  #     belongs.
  # *   The group ID `gid`.
  #
  #
  # Example:
  #
  #     Process.groups                # => [0, 1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
  #     Process.initgroups('me', 30)  # => [30, 6, 10, 11]
  #     Process.groups                # => [30, 6, 10, 11]
  #
  # Not available on all platforms.
  #
  def self.initgroups: (String username, Integer gid) -> ::Array[Integer]

  # <!--
  #   rdoc-file=process.c
  #   - Process.kill(signal, *ids) -> count
  # -->
  # Sends a signal to each process specified by `ids` (which must specify at least
  # one ID); returns the count of signals sent.
  #
  # For each given `id`, if `id` is:
  #
  # *   Positive, sends the signal to the process whose process ID is `id`.
  # *   Zero, send the signal to all processes in the current process group.
  # *   Negative, sends the signal to a system-dependent collection of processes.
  #
  #
  # Argument `signal` specifies the signal to be sent; the argument may be:
  #
  # *   An integer signal number: e.g., `-29`, `0`, `29`.
  # *   A signal name (string), with or without leading `'SIG'`, and with or
  #     without a further prefixed minus sign (`'-'`): e.g.:
  #
  #     *   `'SIGPOLL'`.
  #     *   `'POLL'`,
  #     *   `'-SIGPOLL'`.
  #     *   `'-POLL'`.
  #
  #
  # *   A signal symbol, with or without leading `'SIG'`, and with or without a
  #     further prefixed minus sign (`'-'`): e.g.:
  #
  #     *   `:SIGPOLL`.
  #     *   `:POLL`.
  #     *   `:'-SIGPOLL'`.
  #     *   `:'-POLL'`.
  #
  #
  #
  # If `signal` is:
  #
  # *   A non-negative integer, or a signal name or symbol without prefixed `'-'`,
  #     each process with process ID `id` is signalled.
  # *   A negative integer, or a signal name or symbol with prefixed `'-'`, each
  #     process group with group ID `id` is signalled.
  #
  #
  # Use method Signal.list to see which signals are supported by Ruby on the
  # underlying platform; the method returns a hash of the string names and
  # non-negative integer values of the supported signals. The size and content of
  # the returned hash varies widely among platforms.
  #
  # Additionally, signal `0` is useful to determine if the process exists.
  #
  # Example:
  #
  #     pid = fork do
  #       Signal.trap('HUP') { puts 'Ouch!'; exit }
  #       # ... do some work ...
  #     end
  #     # ...
  #     Process.kill('HUP', pid)
  #     Process.wait
  #
  # Output:
  #
  #     Ouch!
  #
  # Exceptions:
  #
  # *   Raises Errno::EINVAL or RangeError if `signal` is an integer but invalid.
  # *   Raises ArgumentError if `signal` is a string or symbol but invalid.
  # *   Raises Errno::ESRCH or RangeError if one of `ids` is invalid.
  # *   Raises Errno::EPERM if needed permissions are not in force.
  #
  #
  # In the last two cases, signals may have been sent to some processes.
  #
  def self.kill: (Integer | interned signal, *Integer pids) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.maxgroups -> integer
  # -->
  # Returns the maximum number of group IDs allowed in the supplemental group
  # access list:
  #
  #     Process.maxgroups # => 32
  #
  def self.maxgroups: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.maxgroups = new_max -> new_max
  # -->
  # Sets the maximum number of group IDs allowed in the supplemental group access
  # list.
  #
  def self.maxgroups=: (Integer arg0) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.pid -> integer
  # -->
  # Returns the process ID of the current process:
  #
  #     Process.pid # => 15668
  #
  def self.pid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.ppid -> integer
  # -->
  # Returns the process ID of the parent of the current process:
  #
  #     puts "Pid is #{Process.pid}."
  #     fork { puts "Parent pid is #{Process.ppid}." }
  #
  # Output:
  #
  #     Pid is 271290.
  #     Parent pid is 271290.
  #
  # May not return a trustworthy value on certain platforms.
  #
  def self.ppid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.setpgid(pid, pgid) -> 0
  # -->
  # Sets the process group ID for the process given by process ID `pid` to `pgid`.
  #
  # Not available on all platforms.
  #
  def self.setpgid: (Integer pid, Integer arg0) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.setpriority(kind, integer, priority) -> 0
  # -->
  # See Process.getpriority.
  #
  # Examples:
  #
  #     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
  #
  # Not available on all platforms.
  #
  def self.setpriority: (Integer kind, Integer arg0, Integer priority) -> Integer

  # <!--
  #   rdoc-file=ruby.c
  #   - Process.setproctitle(string)  -> string
  # -->
  # Sets the process title that appears on the ps(1) command.  Not necessarily
  # effective on all platforms.  No exception will be raised regardless of the
  # result, nor will NotImplementedError be raised even if the platform does not
  # support the feature.
  #
  # Calling this method does not affect the value of $0.
  #
  #     Process.setproctitle('myapp: worker #%d' % worker_id)
  #
  # This method first appeared in Ruby 2.1 to serve as a global variable free
  # means to change the process title.
  #
  def self.setproctitle: (String arg0) -> String

  # <!--
  #   rdoc-file=process.c
  #   - Process.setrlimit(resource, cur_limit, max_limit = cur_limit) -> nil
  # -->
  # Sets limits for the current process for the given `resource` to `cur_limit`
  # (soft limit) and `max_limit` (hard limit); returns `nil`.
  #
  # Argument `resource` specifies the resource whose limits are to be set; the
  # argument may be given as a symbol, as a string, or as a constant beginning
  # with `Process::RLIMIT_` (e.g., `:CORE`, `'CORE'`, or `Process::RLIMIT_CORE`.
  #
  # The resources available and supported are system-dependent, and may include
  # (here expressed as symbols):
  #
  # *   `:AS`: Total available memory (bytes) (SUSv3, NetBSD, FreeBSD, OpenBSD
  #     except 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).
  # *   `:NPTS`: Number of pseudo terminals (number) (FreeBSD).
  # *   `: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).
  #
  #
  # Arguments `cur_limit` and `max_limit` may be:
  #
  # *   Integers (`max_limit` should not be smaller than `cur_limit`).
  # *   Symbol `:SAVED_MAX`, string `'SAVED_MAX'`, or constant
  #     `Process::RLIM_SAVED_MAX`: saved maximum limit.
  # *   Symbol `:SAVED_CUR`, string `'SAVED_CUR'`, or constant
  #     `Process::RLIM_SAVED_CUR`: saved current limit.
  # *   Symbol `:INFINITY`, string `'INFINITY'`, or constant
  #     `Process::RLIM_INFINITY`: no limit on resource.
  #
  #
  # This 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])
  #
  # Not available on all platforms.
  #
  def self.setrlimit: (interned | Integer resource, Integer cur_limit, ?Integer max_limit) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process.setsid -> integer
  # -->
  # Establishes the current process as a new session and process group leader,
  # with no controlling tty; returns the session ID:
  #
  #     Process.setsid # => 27422
  #
  # Not available on all platforms.
  #
  def self.setsid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.times -> process_tms
  # -->
  # Returns a Process::Tms structure that contains user and system CPU times for
  # the current process, and for its children processes:
  #
  #     Process.times
  #     # => #<struct Process::Tms utime=55.122118, stime=35.533068, cutime=0.0, cstime=0.002846>
  #
  # The precision is platform-defined.
  #
  def self.times: () -> Process::Tms

  # <!--
  #   rdoc-file=process.c
  #   - Process.uid         -> integer
  #   - Process::UID.rid    -> integer
  #   - Process::Sys.getuid -> integer
  # -->
  # Returns the (real) user ID of the current process.
  #
  #     Process.uid # => 1000
  #
  def self.uid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.uid = new_uid -> new_uid
  # -->
  # Sets the (user) user ID for the current process to `new_uid`:
  #
  #     Process.uid = 1000 # => 1000
  #
  # Not available on all platforms.
  #
  def self.uid=: (Integer user) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.wait(pid = -1, flags = 0) -> integer
  # -->
  # Waits for a suitable child process to exit, returns its process ID, and sets
  # `$?` to a Process::Status object containing information on that process. Which
  # child it waits for depends on the value of the given `pid`:
  #
  # *   Positive integer: Waits for the child process whose process ID is `pid`:
  #
  #         pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 230866
  #         pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 230891
  #         Process.wait(pid0)                            # => 230866
  #         $?                                            # => #<Process::Status: pid 230866 exit 13>
  #         Process.wait(pid1)                            # => 230891
  #         $?                                            # => #<Process::Status: pid 230891 exit 14>
  #         Process.wait(pid0)                            # Raises Errno::ECHILD
  #
  # *   `0`: Waits for any child process whose group ID is the same as that of the
  #     current process:
  #
  #         parent_pgpid = Process.getpgid(Process.pid)
  #         puts "Parent process group ID is #{parent_pgpid}."
  #         child0_pid = fork do
  #           puts "Child 0 pid is #{Process.pid}"
  #           child0_pgid = Process.getpgid(Process.pid)
  #           puts "Child 0 process group ID is #{child0_pgid} (same as parent's)."
  #         end
  #         child1_pid = fork do
  #           puts "Child 1 pid is #{Process.pid}"
  #           Process.setpgid(0, Process.pid)
  #           child1_pgid = Process.getpgid(Process.pid)
  #           puts "Child 1 process group ID is #{child1_pgid} (different from parent's)."
  #         end
  #         retrieved_pid = Process.wait(0)
  #         puts "Process.wait(0) returned pid #{retrieved_pid}, which is child 0 pid."
  #         begin
  #           Process.wait(0)
  #         rescue Errno::ECHILD => x
  #           puts "Raised #{x.class}, because child 1 process group ID differs from parent process group ID."
  #         end
  #
  #     Output:
  #
  #         Parent process group ID is 225764.
  #         Child 0 pid is 225788
  #         Child 0 process group ID is 225764 (same as parent's).
  #         Child 1 pid is 225789
  #         Child 1 process group ID is 225789 (different from parent's).
  #         Process.wait(0) returned pid 225788, which is child 0 pid.
  #         Raised Errno::ECHILD, because child 1 process group ID differs from parent process group ID.
  #
  # *   `-1` (default): Waits for any child process:
  #
  #         parent_pgpid = Process.getpgid(Process.pid)
  #         puts "Parent process group ID is #{parent_pgpid}."
  #         child0_pid = fork do
  #           puts "Child 0 pid is #{Process.pid}"
  #           child0_pgid = Process.getpgid(Process.pid)
  #           puts "Child 0 process group ID is #{child0_pgid} (same as parent's)."
  #         end
  #         child1_pid = fork do
  #           puts "Child 1 pid is #{Process.pid}"
  #           Process.setpgid(0, Process.pid)
  #           child1_pgid = Process.getpgid(Process.pid)
  #           puts "Child 1 process group ID is #{child1_pgid} (different from parent's)."
  #           sleep 3 # To force child 1 to exit later than child 0 exit.
  #         end
  #         child_pids = [child0_pid, child1_pid]
  #         retrieved_pid = Process.wait(-1)
  #         puts child_pids.include?(retrieved_pid)
  #         retrieved_pid = Process.wait(-1)
  #         puts child_pids.include?(retrieved_pid)
  #
  #     Output:
  #
  #         Parent process group ID is 228736.
  #         Child 0 pid is 228758
  #         Child 0 process group ID is 228736 (same as parent's).
  #         Child 1 pid is 228759
  #         Child 1 process group ID is 228759 (different from parent's).
  #         true
  #         true
  #
  # *   Less than `-1`: Waits for any child whose process group ID is `-pid`:
  #
  #         parent_pgpid = Process.getpgid(Process.pid)
  #         puts "Parent process group ID is #{parent_pgpid}."
  #         child0_pid = fork do
  #           puts "Child 0 pid is #{Process.pid}"
  #           child0_pgid = Process.getpgid(Process.pid)
  #           puts "Child 0 process group ID is #{child0_pgid} (same as parent's)."
  #         end
  #         child1_pid = fork do
  #           puts "Child 1 pid is #{Process.pid}"
  #           Process.setpgid(0, Process.pid)
  #           child1_pgid = Process.getpgid(Process.pid)
  #           puts "Child 1 process group ID is #{child1_pgid} (different from parent's)."
  #         end
  #         sleep 1
  #         retrieved_pid = Process.wait(-child1_pid)
  #         puts "Process.wait(-child1_pid) returned pid #{retrieved_pid}, which is child 1 pid."
  #         begin
  #           Process.wait(-child1_pid)
  #         rescue Errno::ECHILD => x
  #           puts "Raised #{x.class}, because there's no longer a child with process group id #{child1_pid}."
  #         end
  #
  #     Output:
  #
  #         Parent process group ID is 230083.
  #         Child 0 pid is 230108
  #         Child 0 process group ID is 230083 (same as parent's).
  #         Child 1 pid is 230109
  #         Child 1 process group ID is 230109 (different from parent's).
  #         Process.wait(-child1_pid) returned pid 230109, which is child 1 pid.
  #         Raised Errno::ECHILD, because there's no longer a child with process group id 230109.
  #
  #
  # Argument `flags` should be given as one of the following constants, or as the
  # logical OR of both:
  #
  # *   Process::WNOHANG: Does not block if no child process is available.
  # *   Process:WUNTRACED: May return a stopped child process, even if not yet
  #     reported.
  #
  #
  # Not all flags are available on all platforms.
  #
  # Raises Errno::ECHILD if there is no suitable child process.
  #
  # Not available on all platforms.
  #
  # Process.waitpid is an alias for Process.wait.
  #
  def self.wait: (?Integer pid, ?Integer flags) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.wait2(pid = -1, flags = 0) -> [pid, status]
  # -->
  # Like Process.waitpid, but returns an array containing the child process `pid`
  # and Process::Status `status`:
  #
  #     pid = Process.spawn('ruby', '-e', 'exit 13') # => 309581
  #     Process.wait2(pid)
  #     # => [309581, #<Process::Status: pid 309581 exit 13>]
  #
  # Process.waitpid2 is an alias for Process.waitpid.
  #
  def self.wait2: (?Integer pid, ?Integer flags) -> [ Integer, Process::Status ]

  # <!--
  #   rdoc-file=process.c
  #   - Process.waitall -> array
  # -->
  # Waits for all children, returns an array of 2-element arrays; each subarray
  # contains the integer pid and Process::Status status for one of the reaped
  # child processes:
  #
  #     pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 325470
  #     pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 325495
  #     Process.waitall
  #     # => [[325470, #<Process::Status: pid 325470 exit 13>], [325495, #<Process::Status: pid 325495 exit 14>]]
  #
  def self.waitall: () -> ::Array[[ Integer, Process::Status ]]

  # <!--
  #   rdoc-file=process.c
  #   - Process.wait(pid = -1, flags = 0) -> integer
  # -->
  # Waits for a suitable child process to exit, returns its process ID, and sets
  # `$?` to a Process::Status object containing information on that process. Which
  # child it waits for depends on the value of the given `pid`:
  #
  # *   Positive integer: Waits for the child process whose process ID is `pid`:
  #
  #         pid0 = Process.spawn('ruby', '-e', 'exit 13') # => 230866
  #         pid1 = Process.spawn('ruby', '-e', 'exit 14') # => 230891
  #         Process.wait(pid0)                            # => 230866
  #         $?                                            # => #<Process::Status: pid 230866 exit 13>
  #         Process.wait(pid1)                            # => 230891
  #         $?                                            # => #<Process::Status: pid 230891 exit 14>
  #         Process.wait(pid0)                            # Raises Errno::ECHILD
  #
  # *   `0`: Waits for any child process whose group ID is the same as that of the
  #     current process:
  #
  #         parent_pgpid = Process.getpgid(Process.pid)
  #         puts "Parent process group ID is #{parent_pgpid}."
  #         child0_pid = fork do
  #           puts "Child 0 pid is #{Process.pid}"
  #           child0_pgid = Process.getpgid(Process.pid)
  #           puts "Child 0 process group ID is #{child0_pgid} (same as parent's)."
  #         end
  #         child1_pid = fork do
  #           puts "Child 1 pid is #{Process.pid}"
  #           Process.setpgid(0, Process.pid)
  #           child1_pgid = Process.getpgid(Process.pid)
  #           puts "Child 1 process group ID is #{child1_pgid} (different from parent's)."
  #         end
  #         retrieved_pid = Process.wait(0)
  #         puts "Process.wait(0) returned pid #{retrieved_pid}, which is child 0 pid."
  #         begin
  #           Process.wait(0)
  #         rescue Errno::ECHILD => x
  #           puts "Raised #{x.class}, because child 1 process group ID differs from parent process group ID."
  #         end
  #
  #     Output:
  #
  #         Parent process group ID is 225764.
  #         Child 0 pid is 225788
  #         Child 0 process group ID is 225764 (same as parent's).
  #         Child 1 pid is 225789
  #         Child 1 process group ID is 225789 (different from parent's).
  #         Process.wait(0) returned pid 225788, which is child 0 pid.
  #         Raised Errno::ECHILD, because child 1 process group ID differs from parent process group ID.
  #
  # *   `-1` (default): Waits for any child process:
  #
  #         parent_pgpid = Process.getpgid(Process.pid)
  #         puts "Parent process group ID is #{parent_pgpid}."
  #         child0_pid = fork do
  #           puts "Child 0 pid is #{Process.pid}"
  #           child0_pgid = Process.getpgid(Process.pid)
  #           puts "Child 0 process group ID is #{child0_pgid} (same as parent's)."
  #         end
  #         child1_pid = fork do
  #           puts "Child 1 pid is #{Process.pid}"
  #           Process.setpgid(0, Process.pid)
  #           child1_pgid = Process.getpgid(Process.pid)
  #           puts "Child 1 process group ID is #{child1_pgid} (different from parent's)."
  #           sleep 3 # To force child 1 to exit later than child 0 exit.
  #         end
  #         child_pids = [child0_pid, child1_pid]
  #         retrieved_pid = Process.wait(-1)
  #         puts child_pids.include?(retrieved_pid)
  #         retrieved_pid = Process.wait(-1)
  #         puts child_pids.include?(retrieved_pid)
  #
  #     Output:
  #
  #         Parent process group ID is 228736.
  #         Child 0 pid is 228758
  #         Child 0 process group ID is 228736 (same as parent's).
  #         Child 1 pid is 228759
  #         Child 1 process group ID is 228759 (different from parent's).
  #         true
  #         true
  #
  # *   Less than `-1`: Waits for any child whose process group ID is `-pid`:
  #
  #         parent_pgpid = Process.getpgid(Process.pid)
  #         puts "Parent process group ID is #{parent_pgpid}."
  #         child0_pid = fork do
  #           puts "Child 0 pid is #{Process.pid}"
  #           child0_pgid = Process.getpgid(Process.pid)
  #           puts "Child 0 process group ID is #{child0_pgid} (same as parent's)."
  #         end
  #         child1_pid = fork do
  #           puts "Child 1 pid is #{Process.pid}"
  #           Process.setpgid(0, Process.pid)
  #           child1_pgid = Process.getpgid(Process.pid)
  #           puts "Child 1 process group ID is #{child1_pgid} (different from parent's)."
  #         end
  #         sleep 1
  #         retrieved_pid = Process.wait(-child1_pid)
  #         puts "Process.wait(-child1_pid) returned pid #{retrieved_pid}, which is child 1 pid."
  #         begin
  #           Process.wait(-child1_pid)
  #         rescue Errno::ECHILD => x
  #           puts "Raised #{x.class}, because there's no longer a child with process group id #{child1_pid}."
  #         end
  #
  #     Output:
  #
  #         Parent process group ID is 230083.
  #         Child 0 pid is 230108
  #         Child 0 process group ID is 230083 (same as parent's).
  #         Child 1 pid is 230109
  #         Child 1 process group ID is 230109 (different from parent's).
  #         Process.wait(-child1_pid) returned pid 230109, which is child 1 pid.
  #         Raised Errno::ECHILD, because there's no longer a child with process group id 230109.
  #
  #
  # Argument `flags` should be given as one of the following constants, or as the
  # logical OR of both:
  #
  # *   Process::WNOHANG: Does not block if no child process is available.
  # *   Process:WUNTRACED: May return a stopped child process, even if not yet
  #     reported.
  #
  #
  # Not all flags are available on all platforms.
  #
  # Raises Errno::ECHILD if there is no suitable child process.
  #
  # Not available on all platforms.
  #
  # Process.waitpid is an alias for Process.wait.
  #
  def self.waitpid: (?Integer pid, ?Integer flags) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.wait2(pid = -1, flags = 0) -> [pid, status]
  # -->
  # Like Process.waitpid, but returns an array containing the child process `pid`
  # and Process::Status `status`:
  #
  #     pid = Process.spawn('ruby', '-e', 'exit 13') # => 309581
  #     Process.wait2(pid)
  #     # => [309581, #<Process::Status: pid 309581 exit 13>]
  #
  # Process.waitpid2 is an alias for Process.waitpid.
  #
  def self.waitpid2: (?Integer pid, ?Integer flags) -> [ Integer, Process::Status ]

  # <!--
  #   rdoc-file=process.c
  #   - Process.warmup    -> true
  # -->
  # Notify the Ruby virtual machine that the boot sequence is finished, and that
  # now is a good time to optimize the application. This is useful for long
  # running applications.
  #
  # This method is expected to be called at the end of the application boot. If
  # the application is deployed using a pre-forking model, `Process.warmup` should
  # be called in the original process before the first fork.
  #
  # The actual optimizations performed are entirely implementation specific and
  # may change in the future without notice.
  #
  # On CRuby, `Process.warmup`:
  #
  # *   Performs a major GC.
  # *   Compacts the heap.
  # *   Promotes all surviving objects to the old generation.
  # *   Precomputes the coderange of all strings.
  # *   Frees all empty heap pages and increments the allocatable pages counter by
  #     the number of pages freed.
  # *   Invoke `malloc_trim` if available to free empty malloc pages.
  #
  def self.warmup: () -> bool
end

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_BOOTTIME: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_BOOTTIME_ALARM: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_MONOTONIC: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_MONOTONIC_COARSE: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_MONOTONIC_RAW: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_PROCESS_CPUTIME_ID: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_REALTIME: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_REALTIME_ALARM: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_REALTIME_COARSE: Integer

# <!-- rdoc-file=process.c -->
# see Process.clock_gettime
#
Process::CLOCK_THREAD_CPUTIME_ID: Integer

# <!-- rdoc-file=process.c -->
# see Process.setpriority
#
Process::PRIO_PGRP: Integer

# <!-- rdoc-file=process.c -->
# see Process.setpriority
#
Process::PRIO_PROCESS: Integer

# <!-- rdoc-file=process.c -->
# see Process.setpriority
#
Process::PRIO_USER: Integer

# <!-- rdoc-file=process.c -->
# Maximum size of the process's virtual memory (address space) in bytes.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_AS: Integer

# <!-- rdoc-file=process.c -->
# Maximum size of the core file.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_CORE: Integer

# <!-- rdoc-file=process.c -->
# CPU time limit in seconds.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_CPU: Integer

# <!-- rdoc-file=process.c -->
# Maximum size of the process's data segment.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_DATA: Integer

# <!-- rdoc-file=process.c -->
# Maximum size of files that the process may create.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_FSIZE: Integer

# <!-- rdoc-file=process.c -->
# Maximum number of bytes of memory that may be locked into RAM.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_MEMLOCK: Integer

# <!-- rdoc-file=process.c -->
# 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.
#
Process::RLIMIT_MSGQUEUE: Integer

# <!-- rdoc-file=process.c -->
# Specifies a ceiling to which the process's nice value can be raised.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_NICE: Integer

# <!-- rdoc-file=process.c -->
# 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.
#
Process::RLIMIT_NOFILE: Integer

# <!-- rdoc-file=process.c -->
# 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.
#
Process::RLIMIT_NPROC: Integer

# <!-- rdoc-file=process.c -->
# The maximum number of pseudo-terminals that can be created for the real user
# ID of the calling process.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_NPTS: Integer

# <!-- rdoc-file=process.c -->
# Specifies the limit (in pages) of the process's resident set.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_RSS: Integer

# <!-- rdoc-file=process.c -->
# Specifies a ceiling on the real-time priority that may be set for this
# process.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_RTPRIO: Integer

# <!-- rdoc-file=process.c -->
# Specifies limit on CPU time this process scheduled under a real-time
# scheduling policy can consume.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_RTTIME: Integer

# <!-- rdoc-file=process.c -->
# 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.
#
Process::RLIMIT_SIGPENDING: Integer

# <!-- rdoc-file=process.c -->
# Maximum size of the stack, in bytes.
#
# see the system getrlimit(2) manual for details.
#
Process::RLIMIT_STACK: Integer

# <!-- rdoc-file=process.c -->
# see Process.setrlimit
#
Process::RLIM_INFINITY: Integer

# <!-- rdoc-file=process.c -->
# see Process.setrlimit
#
Process::RLIM_SAVED_CUR: Integer

# <!-- rdoc-file=process.c -->
# see Process.setrlimit
#
Process::RLIM_SAVED_MAX: Integer

# <!-- rdoc-file=process.c -->
# see Process.wait
#
Process::WNOHANG: Integer

# <!-- rdoc-file=process.c -->
# see Process.wait
#
Process::WUNTRACED: Integer

# <!-- rdoc-file=process.c -->
# The Process::GID module contains a collection of module functions which can be
# used to portably get, set, and switch the current process's real, effective,
# and saved group IDs.
#
module Process::GID
  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.change_privilege(group)   -> integer
  # -->
  # Change the current process's real and effective group ID to that specified by
  # *group*. Returns the new group ID. Not available on all platforms.
  #
  #     [Process.gid, Process.egid]          #=> [0, 0]
  #     Process::GID.change_privilege(33)    #=> 33
  #     [Process.gid, Process.egid]          #=> [33, 33]
  #
  def self.change_privilege: (Integer group) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.egid        -> integer
  #   - Process::GID.eid    -> integer
  #   - Process::Sys.geteid -> integer
  # -->
  # Returns the effective group ID for the current process:
  #
  #     Process.egid # => 500
  #
  # Not available on all platforms.
  #
  def self.eid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.from_name(name)   -> gid
  # -->
  # Get the group ID by the *name*. If the group is not found, `ArgumentError`
  # will be raised.
  #
  #     Process::GID.from_name("wheel") #=> 0
  #     Process::GID.from_name("nosuchgroup") #=> can't find group for nosuchgroup (ArgumentError)
  #
  def self.from_name: (String name) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.grant_privilege(group)    -> integer
  #   - Process::GID.eid = group               -> integer
  # -->
  # Set the effective group ID, and if possible, the saved group ID of the process
  # to the given *group*. Returns the new effective group ID. Not available on all
  # platforms.
  #
  #     [Process.gid, Process.egid]          #=> [0, 0]
  #     Process::GID.grant_privilege(31)     #=> 33
  #     [Process.gid, Process.egid]          #=> [0, 33]
  #
  def self.grant_privilege: (Integer group) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.re_exchange   -> integer
  # -->
  # Exchange real and effective group IDs and return the new effective group ID.
  # Not available on all platforms.
  #
  #     [Process.gid, Process.egid]   #=> [0, 33]
  #     Process::GID.re_exchange      #=> 0
  #     [Process.gid, Process.egid]   #=> [33, 0]
  #
  def self.re_exchange: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.re_exchangeable?   -> true or false
  # -->
  # Returns `true` if the real and effective group IDs of a process may be
  # exchanged on the current platform.
  #
  def self.re_exchangeable?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - Process.gid         -> integer
  #   - Process::GID.rid    -> integer
  #   - Process::Sys.getgid -> integer
  # -->
  # Returns the (real) group ID for the current process:
  #
  #     Process.gid # => 1000
  #
  def self.rid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.sid_available?   -> true or false
  # -->
  # Returns `true` if the current platform has saved group ID functionality.
  #
  def self.sid_available?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - Process::GID.switch              -> integer
  #   - Process::GID.switch {|| block}   -> object
  # -->
  # Switch the effective and real group IDs of the current process. If a *block*
  # is given, the group IDs will be switched back after the block is executed.
  # Returns the new effective group ID if called without a block, and the return
  # value of the block if one is given.
  #
  def self.switch: () -> Integer
                 | [T] () { () -> T } -> T

  def self.eid=: (Integer group) -> Integer
end

# <!-- rdoc-file=process.c -->
# A Process::Status contains information about a system process.
#
# Thread-local variable `$?` is initially `nil`. Some methods assign to it a
# Process::Status object that represents a system process (either running or
# terminated):
#
#     `ruby -e "exit 99"`
#     stat = $?       # => #<Process::Status: pid 1262862 exit 99>
#     stat.class      # => Process::Status
#     stat.to_i       # => 25344
#     stat >> 8       # => 99
#     stat.stopped?   # => false
#     stat.exited?    # => true
#     stat.exitstatus # => 99
#
class Process::Status < Object
  # <!--
  #   rdoc-file=process.c
  #   - stat & mask -> integer
  # -->
  # This method is deprecated; use other attribute methods.
  #
  # Returns the logical AND of the value of #to_i with `mask`:
  #
  #     `cat /nop`
  #     stat = $?                 # => #<Process::Status: pid 1155508 exit 1>
  #     sprintf('%x', stat.to_i)  # => "100"
  #     stat & 0x00               # => 0
  #
  # ArgumentError is raised if `mask` is negative.
  #
  def &: (Integer num) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - stat == other -> true or false
  # -->
  # Returns whether the value of #to_i == `other`:
  #
  #     `cat /nop`
  #     stat = $?                # => #<Process::Status: pid 1170366 exit 1>
  #     sprintf('%x', stat.to_i) # => "100"
  #     stat == 0x100            # => true
  #
  def ==: (untyped other) -> bool

  # <!--
  #   rdoc-file=process.c
  #   - stat >> places -> integer
  # -->
  # This method is deprecated; use other predicate methods.
  #
  # Returns the value of #to_i, shifted `places` to the right:
  #
  #     `cat /nop`
  #     stat = $?                 # => #<Process::Status: pid 1155508 exit 1>
  #     stat.to_i                 # => 256
  #     stat >> 1                 # => 128
  #     stat >> 2                 # => 64
  #
  # ArgumentError is raised if `places` is negative.
  #
  def >>: (Integer num) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - coredump? -> true or false
  # -->
  # Returns `true` if the process generated a coredump when it terminated, `false`
  # if not.
  #
  # Not available on all platforms.
  #
  def coredump?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - exited? -> true or false
  # -->
  # Returns `true` if the process exited normally (for example using an `exit()`
  # call or finishing the program), `false` if not.
  #
  def exited?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - exitstatus -> integer or nil
  # -->
  # Returns the least significant eight bits of the return code of the process if
  # it has exited; `nil` otherwise:
  #
  #     `exit 99`
  #     $?.exitstatus # => 99
  #
  def exitstatus: () -> Integer?

  # <!--
  #   rdoc-file=process.c
  #   - inspect -> string
  # -->
  # Returns a string representation of `self`:
  #
  #     system("false")
  #     $?.inspect # => "#<Process::Status: pid 1303494 exit 1>"
  #
  def inspect: () -> String

  # <!--
  #   rdoc-file=process.c
  #   - pid -> integer
  # -->
  # Returns the process ID of the process:
  #
  #     system("false")
  #     $?.pid # => 1247002
  #
  def pid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - signaled? -> true or false
  # -->
  # Returns `true` if the process terminated because of an uncaught signal,
  # `false` otherwise.
  #
  def signaled?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - stopped? -> true or false
  # -->
  # Returns `true` if this process is stopped, and if the corresponding #wait call
  # had the Process::WUNTRACED flag set, `false` otherwise.
  #
  def stopped?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - stopsig -> integer or nil
  # -->
  # Returns the number of the signal that caused the process to stop, or `nil` if
  # the process is not stopped.
  #
  def stopsig: () -> Integer?

  # <!--
  #   rdoc-file=process.c
  #   - success? -> true, false, or nil
  # -->
  # Returns:
  #
  # *   `true` if the process has completed successfully and exited.
  # *   `false` if the process has completed unsuccessfully and exited.
  # *   `nil` if the process has not exited.
  #
  def success?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - termsig -> integer or nil
  # -->
  # Returns the number of the signal that caused the process to terminate or `nil`
  # if the process was not terminated by an uncaught signal.
  #
  def termsig: () -> Integer?

  # <!--
  #   rdoc-file=process.c
  #   - to_i     -> integer
  # -->
  # Returns the system-dependent integer status of `self`:
  #
  #     `cat /nop`
  #     $?.to_i # => 256
  #
  def to_i: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - to_s -> string
  # -->
  # Returns a string representation of `self`:
  #
  #     `cat /nop`
  #     $?.to_s # => "pid 1262141 exit 1"
  #
  def to_s: () -> String
end

# <!-- rdoc-file=process.c -->
# The Process::Sys module contains UID and GID functions which provide direct
# bindings to the system calls of the same names instead of the more-portable
# versions of the same functionality found in the Process, Process::UID, and
# Process::GID modules.
#
module Process::Sys
  # <!--
  #   rdoc-file=process.c
  #   - Process.euid         -> integer
  #   - Process::UID.eid     -> integer
  #   - Process::Sys.geteuid -> integer
  # -->
  # Returns the effective user ID for the current process.
  #
  #     Process.euid # => 501
  #
  def self.geteuid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.gid         -> integer
  #   - Process::GID.rid    -> integer
  #   - Process::Sys.getgid -> integer
  # -->
  # Returns the (real) group ID for the current process:
  #
  #     Process.gid # => 1000
  #
  def self.getgid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.uid         -> integer
  #   - Process::UID.rid    -> integer
  #   - Process::Sys.getuid -> integer
  # -->
  # Returns the (real) user ID of the current process.
  #
  #     Process.uid # => 1000
  #
  def self.getuid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.issetugid   -> true or false
  # -->
  # Returns `true` if the process was created as a result of an execve(2) system
  # call which had either of the setuid or setgid bits set (and extra privileges
  # were given as a result) or if it has changed any of its real, effective or
  # saved user or group IDs since it began execution.
  #
  def self.issetugid: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setegid(group)   -> nil
  # -->
  # Set the effective group ID of the calling process to *group*.  Not available
  # on all platforms.
  #
  def self.setegid: (Integer group) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.seteuid(user)   -> nil
  # -->
  # Set the effective user ID of the calling process to *user*.  Not available on
  # all platforms.
  #
  def self.seteuid: (Integer user) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setgid(group)   -> nil
  # -->
  # Set the group ID of the current process to *group*. Not available on all
  # platforms.
  #
  def self.setgid: (Integer group) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setregid(rid, eid)   -> nil
  # -->
  # Sets the (group) real and/or effective group IDs of the current process to
  # *rid* and *eid*, respectively. A value of `-1` for either means to leave that
  # ID unchanged. Not available on all platforms.
  #
  def self.setregid: (Integer rid, Integer eid) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setresgid(rid, eid, sid)   -> nil
  # -->
  # Sets the (group) real, effective, and saved user IDs of the current process to
  # *rid*, *eid*, and *sid* respectively. A value of `-1` for any value means to
  # leave that ID unchanged. Not available on all platforms.
  #
  def self.setresgid: (Integer rid, Integer eid, Integer sid) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setresuid(rid, eid, sid)   -> nil
  # -->
  # Sets the (user) real, effective, and saved user IDs of the current process to
  # *rid*, *eid*, and *sid* respectively. A value of `-1` for any value means to
  # leave that ID unchanged. Not available on all platforms.
  #
  def self.setresuid: (Integer rid, Integer eid, Integer sid) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setreuid(rid, eid)   -> nil
  # -->
  # Sets the (user) real and/or effective user IDs of the current process to *rid*
  # and *eid*, respectively. A value of `-1` for either means to leave that ID
  # unchanged. Not available on all platforms.
  #
  def self.setreuid: (Integer rid, Integer eid) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setrgid(group)   -> nil
  # -->
  # Set the real group ID of the calling process to *group*. Not available on all
  # platforms.
  #
  def self.setrgid: (Integer group) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setruid(user)   -> nil
  # -->
  # Set the real user ID of the calling process to *user*. Not available on all
  # platforms.
  #
  def self.setruid: (Integer user) -> nil

  # <!--
  #   rdoc-file=process.c
  #   - Process::Sys.setuid(user)   -> nil
  # -->
  # Set the user ID of the current process to *user*. Not available on all
  # platforms.
  #
  def self.setuid: (Integer user) -> nil
end

# <!-- rdoc-file=process.c -->
# The Process::UID module contains a collection of module functions which can be
# used to portably get, set, and switch the current process's real, effective,
# and saved user IDs.
#
module Process::UID
  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.change_privilege(user)   -> integer
  # -->
  # Change the current process's real and effective user ID to that specified by
  # *user*. Returns the new user ID. Not available on all platforms.
  #
  #     [Process.uid, Process.euid]          #=> [0, 0]
  #     Process::UID.change_privilege(31)    #=> 31
  #     [Process.uid, Process.euid]          #=> [31, 31]
  #
  def self.change_privilege: (Integer user) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process.euid         -> integer
  #   - Process::UID.eid     -> integer
  #   - Process::Sys.geteuid -> integer
  # -->
  # Returns the effective user ID for the current process.
  #
  #     Process.euid # => 501
  #
  def self.eid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.from_name(name)   -> uid
  # -->
  # Get the user ID by the *name*. If the user is not found, `ArgumentError` will
  # be raised.
  #
  #     Process::UID.from_name("root") #=> 0
  #     Process::UID.from_name("nosuchuser") #=> can't find user for nosuchuser (ArgumentError)
  #
  def self.from_name: (String name) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.grant_privilege(user)   -> integer
  #   - Process::UID.eid= user               -> integer
  # -->
  # Set the effective user ID, and if possible, the saved user ID of the process
  # to the given *user*. Returns the new effective user ID. Not available on all
  # platforms.
  #
  #     [Process.uid, Process.euid]          #=> [0, 0]
  #     Process::UID.grant_privilege(31)     #=> 31
  #     [Process.uid, Process.euid]          #=> [0, 31]
  #
  def self.grant_privilege: (Integer user) -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.re_exchange   -> integer
  # -->
  # Exchange real and effective user IDs and return the new effective user ID. Not
  # available on all platforms.
  #
  #     [Process.uid, Process.euid]   #=> [0, 31]
  #     Process::UID.re_exchange      #=> 0
  #     [Process.uid, Process.euid]   #=> [31, 0]
  #
  def self.re_exchange: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.re_exchangeable?   -> true or false
  # -->
  # Returns `true` if the real and effective user IDs of a process may be
  # exchanged on the current platform.
  #
  def self.re_exchangeable?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - Process.uid         -> integer
  #   - Process::UID.rid    -> integer
  #   - Process::Sys.getuid -> integer
  # -->
  # Returns the (real) user ID of the current process.
  #
  #     Process.uid # => 1000
  #
  def self.rid: () -> Integer

  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.sid_available?   -> true or false
  # -->
  # Returns `true` if the current platform has saved user ID functionality.
  #
  def self.sid_available?: () -> bool

  # <!--
  #   rdoc-file=process.c
  #   - Process::UID.switch              -> integer
  #   - Process::UID.switch {|| block}   -> object
  # -->
  # Switch the effective and real user IDs of the current process. If a *block* is
  # given, the user IDs will be switched back after the block is executed. Returns
  # the new effective user ID if called without a block, and the return value of
  # the block if one is given.
  #
  def self.switch: () -> Integer
                 | [T] () { () -> T } -> T

  def self.eid=: (Integer user) -> Integer
end

# <!-- rdoc-file=process.c -->
# Placeholder for rusage
#
class Process::Tms < Struct[Float]
end

class Process::Waiter < Thread
  def pid: () -> Integer
end
