mirror of
https://github.com/mistergibson/gxg-web-client.git
synced 2026-08-15 11:34:29 -07:00
794 lines
18 KiB
Ruby
794 lines
18 KiB
Ruby
module Process
|
|
def self.time
|
|
Rubinius.primitive :vm_time
|
|
raise PrimitiveFailure, "Process.time primitive failed"
|
|
end
|
|
|
|
def self.cpu_times
|
|
Rubinius.primitive :vm_times
|
|
raise PrimitiveFailure, "Process.cpu_times primitive failed"
|
|
end
|
|
|
|
##
|
|
# Sets the process title. Calling this method does not affect the value of
|
|
# `$0` as per MRI behaviour. This method returns the title set.
|
|
#
|
|
# @param [String] title
|
|
# @return [Title]
|
|
#
|
|
def self.setproctitle(title)
|
|
val = Rubinius::Type.coerce_to(title, String, :to_str)
|
|
|
|
Rubinius.invoke_primitive(:vm_set_process_title, val)
|
|
end
|
|
|
|
def self.setrlimit(resource, cur_limit, max_limit=undefined)
|
|
resource = coerce_rlimit_resource(resource)
|
|
cur_limit = Rubinius::Type.coerce_to cur_limit, Integer, :to_int
|
|
|
|
unless undefined.equal? max_limit
|
|
max_limit = Rubinius::Type.coerce_to max_limit, Integer, :to_int
|
|
end
|
|
|
|
rlimit = Rlimit.new
|
|
rlimit[:rlim_cur] = cur_limit
|
|
rlimit[:rlim_max] = undefined.equal?(max_limit) ? cur_limit : max_limit
|
|
|
|
ret = FFI::Platform::POSIX.setrlimit(resource, rlimit.pointer)
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def self.getrlimit(resource)
|
|
resource = coerce_rlimit_resource(resource)
|
|
|
|
lim_max = []
|
|
rlimit = Rlimit.new
|
|
ret = FFI::Platform::POSIX.getrlimit(resource, rlimit.pointer)
|
|
Errno.handle if ret == -1
|
|
|
|
[rlimit[:rlim_cur], rlimit[:rlim_max]]
|
|
end
|
|
|
|
def self.setsid
|
|
pgid = FFI::Platform::POSIX.setsid
|
|
Errno.handle if pgid == -1
|
|
pgid
|
|
end
|
|
|
|
def self.fork
|
|
pid = Rubinius::Mirror::Process.fork
|
|
|
|
if block_given? and pid.nil?
|
|
begin
|
|
yield nil
|
|
status = 0
|
|
rescue SystemExit => e
|
|
status = e.status
|
|
rescue Exception => e
|
|
e.render "An exception occurred in a forked block"
|
|
status = 1
|
|
end
|
|
|
|
until Rubinius::AtExit.empty?
|
|
begin
|
|
Rubinius::AtExit.shift.call
|
|
rescue SystemExit => e
|
|
status = e.status
|
|
end
|
|
end
|
|
|
|
# Do not use Kernel.exit. This raises a SystemExit exception, which
|
|
# will run ensure blocks. This is not what MRI does and causes bugs
|
|
# in programs. See issue http://github.com/rubinius/rubinius/issues#issue/289 for
|
|
# an example
|
|
|
|
Kernel.exit! status
|
|
end
|
|
pid
|
|
end
|
|
|
|
def self.times
|
|
Struct::Tms.new(*cpu_times)
|
|
end
|
|
|
|
def self.kill(signal, *pids)
|
|
raise ArgumentError, "PID argument required" if pids.length == 0
|
|
|
|
use_process_group = false
|
|
signal = signal.to_s if signal.kind_of?(Symbol)
|
|
|
|
if signal.kind_of?(String)
|
|
if signal[0] == ?-
|
|
signal = signal[1..-1]
|
|
use_process_group = true
|
|
end
|
|
|
|
if signal[0..2] == "SIG"
|
|
signal = signal[3..-1]
|
|
end
|
|
|
|
signal = Signal::Names[signal]
|
|
end
|
|
|
|
raise ArgumentError unless signal.kind_of? Fixnum
|
|
|
|
if signal < 0
|
|
signal = -signal
|
|
use_process_group = true
|
|
end
|
|
|
|
pids.each do |pid|
|
|
pid = Rubinius::Type.coerce_to_pid pid
|
|
|
|
pid = -pid if use_process_group
|
|
result = FFI::Platform::POSIX.kill(pid, signal)
|
|
|
|
Errno.handle if result == -1
|
|
end
|
|
|
|
return pids.length
|
|
end
|
|
|
|
def self.abort(msg=nil)
|
|
if msg
|
|
msg = StringValue(msg)
|
|
$stderr.puts(msg)
|
|
end
|
|
raise SystemExit.new(1, msg)
|
|
end
|
|
|
|
def self.getpgid(pid)
|
|
pid = Rubinius::Type.coerce_to pid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.getpgid(pid)
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.setpgid(pid, int)
|
|
pid = Rubinius::Type.coerce_to pid, Integer, :to_int
|
|
int = Rubinius::Type.coerce_to int, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setpgid(pid, int)
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
@maxgroups = 32
|
|
class << self
|
|
attr_reader :maxgroups
|
|
def maxgroups=(m)
|
|
@maxgroups = m
|
|
end
|
|
end
|
|
|
|
def self.setpgrp
|
|
setpgid(0, 0)
|
|
end
|
|
def self.getpgrp
|
|
ret = FFI::Platform::POSIX.getpgrp
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.pid
|
|
ret = FFI::Platform::POSIX.getpid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.ppid
|
|
ret = FFI::Platform::POSIX.getppid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.uid=(uid)
|
|
# the 4 rescue clauses below are needed
|
|
# until respond_to? can be used to query the implementation of methods attached via FFI
|
|
# atm respond_to returns true if a method is attached but not implemented on the platform
|
|
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
|
|
begin
|
|
ret = FFI::Platform::POSIX.setresuid(uid, -1, -1)
|
|
rescue NotImplementedError
|
|
begin
|
|
ret = FFI::Platform::POSIX.setreuid(uid, -1)
|
|
rescue NotImplementedError
|
|
begin
|
|
ret = FFI::Platform::POSIX.setruid(uid)
|
|
rescue NotImplementedError
|
|
if Process.euid == uid
|
|
ret = FFI::Platform::POSIX.setuid(uid)
|
|
else
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Errno.handle if ret == -1
|
|
|
|
uid
|
|
end
|
|
|
|
def self.gid=(gid)
|
|
gid = Rubinius::Type.coerce_to gid, Integer, :to_int
|
|
Process::Sys.setgid gid
|
|
end
|
|
|
|
def self.euid=(uid)
|
|
# the 4 rescue clauses below are needed
|
|
# until respond_to? can be used to query the implementation of methods attached via FFI
|
|
# atm respond_to returns true if a method is attached but not implemented on the platform
|
|
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
|
|
begin
|
|
ret = FFI::Platform::POSIX.setresuid(-1, uid, -1)
|
|
rescue NotImplementedError
|
|
begin
|
|
ret = FFI::Platform::POSIX.setreuid(-1, uid)
|
|
rescue NotImplementedError
|
|
begin
|
|
ret = FFI::Platform::POSIX.seteuid(uid)
|
|
rescue NotImplementedError
|
|
if Process.uid == uid
|
|
ret = FFI::Platform::POSIX.setuid(uid)
|
|
else
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Errno.handle if ret == -1
|
|
|
|
uid
|
|
end
|
|
|
|
def self.egid=(gid)
|
|
gid = Rubinius::Type.coerce_to gid, Integer, :to_int
|
|
Process::Sys.setegid gid
|
|
end
|
|
|
|
def self.uid
|
|
ret = FFI::Platform::POSIX.getuid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.gid
|
|
ret = FFI::Platform::POSIX.getgid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.euid
|
|
ret = FFI::Platform::POSIX.geteuid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.egid
|
|
ret = FFI::Platform::POSIX.getegid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.getpriority(kind, id)
|
|
kind = Rubinius::Type.coerce_to kind, Integer, :to_int
|
|
id = Rubinius::Type.coerce_to id, Integer, :to_int
|
|
|
|
FFI::Platform::POSIX.errno = 0
|
|
ret = FFI::Platform::POSIX.getpriority(kind, id)
|
|
Errno.handle
|
|
ret
|
|
end
|
|
|
|
def self.setpriority(kind, id, priority)
|
|
kind = Rubinius::Type.coerce_to kind, Integer, :to_int
|
|
id = Rubinius::Type.coerce_to id, Integer, :to_int
|
|
priority = Rubinius::Type.coerce_to priority, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setpriority(kind, id, priority)
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def self.groups
|
|
g = []
|
|
count = Rubinius::FFI::Platform::POSIX.getgroups(0, nil)
|
|
FFI::MemoryPointer.new(:int, count) { |p|
|
|
num_groups = FFI::Platform::POSIX.getgroups(count, p)
|
|
Errno.handle if num_groups == -1
|
|
g = p.read_array_of_int(num_groups)
|
|
}
|
|
g
|
|
end
|
|
|
|
def self.groups=(g)
|
|
@maxgroups = g.length if g.length > @maxgroups
|
|
FFI::MemoryPointer.new(:int, @maxgroups) { |p|
|
|
p.write_array_of_int(g)
|
|
Errno.handle if FFI::Platform::POSIX.setgroups(g.length, p) == -1
|
|
}
|
|
g
|
|
end
|
|
|
|
def self.initgroups(username, gid)
|
|
username = StringValue(username)
|
|
gid = Rubinius::Type.coerce_to gid, Integer, :to_int
|
|
|
|
if FFI::Platform::POSIX.initgroups(username, gid) == -1
|
|
Errno.handle
|
|
end
|
|
|
|
Process.groups
|
|
end
|
|
|
|
#
|
|
# Wait for the given process to exit.
|
|
#
|
|
# The pid may be the specific pid of some previously forked
|
|
# process, or -1 to indicate to watch for *any* child process
|
|
# exiting. Other options, such as process groups, may be available
|
|
# depending on the system.
|
|
#
|
|
# With no arguments the default is to block waiting for any
|
|
# child processes (pid -1.)
|
|
#
|
|
# The flag may be Process::WNOHANG, which indicates that
|
|
# the child should only be quickly checked. If it has not
|
|
# exited yet, nil is returned immediately instead.
|
|
#
|
|
# The return value is the exited pid or nil if Process::WNOHANG
|
|
# was used and the child had not yet exited.
|
|
#
|
|
# If the pid has exited, the global $? is set to a Process::Status
|
|
# object representing the exit status (and possibly other info) of
|
|
# the child.
|
|
#
|
|
# If there exists no such pid (e.g. never forked or already
|
|
# waited for), or no children at all, Errno::ECHILD is raised.
|
|
#
|
|
# TODO: Support other options such as WUNTRACED? --rue
|
|
#
|
|
def self.wait2(input_pid=-1, flags=nil)
|
|
input_pid = Rubinius::Type.coerce_to input_pid, Integer, :to_int
|
|
|
|
if flags and (flags & WNOHANG) == WNOHANG
|
|
value = Rubinius.invoke_primitive :vm_waitpid, input_pid, true
|
|
return if value.nil?
|
|
else
|
|
value = Rubinius.invoke_primitive :vm_waitpid, input_pid, false
|
|
end
|
|
|
|
if value == false
|
|
raise Errno::ECHILD, "No child process: #{input_pid}"
|
|
end
|
|
|
|
# vm_waitpid returns a tuple when wait needs to communicate the pid that
|
|
# was actually detected as stopped (since wait can wait for all child
|
|
# pids, groups, etc)
|
|
status, termsig, stopsig, pid = value
|
|
|
|
status = Process::Status.new(pid, status, termsig, stopsig)
|
|
Rubinius::Mirror::Process.set_status_global status
|
|
|
|
[pid, status]
|
|
end
|
|
|
|
#
|
|
# Wait for all child processes.
|
|
#
|
|
# Blocks until all child processes have exited, and returns
|
|
# an Array of [pid, Process::Status] results, one for each
|
|
# child.
|
|
#
|
|
# Be mindful of the effects of creating new processes while
|
|
# .waitall has been called (usually in a different thread.)
|
|
# The .waitall call does not in any way check that it is only
|
|
# waiting for children that existed at the time it was called.
|
|
#
|
|
def self.waitall
|
|
statuses = []
|
|
|
|
begin
|
|
while true
|
|
statuses << Process.wait2
|
|
end
|
|
rescue Errno::ECHILD
|
|
end
|
|
|
|
statuses
|
|
end
|
|
|
|
def self.wait(pid=-1, flags=nil)
|
|
pid, status = Process.wait2(pid, flags)
|
|
return pid
|
|
end
|
|
|
|
class << self
|
|
alias_method :waitpid, :wait
|
|
alias_method :waitpid2, :wait2
|
|
end
|
|
|
|
def self.daemon(stay_in_dir=false, keep_stdio_open=false)
|
|
# Do not run at_exit handlers in the parent
|
|
exit!(0) if fork
|
|
|
|
Process.setsid
|
|
|
|
exit!(0) if fork
|
|
|
|
Dir.chdir("/") unless stay_in_dir
|
|
|
|
unless keep_stdio_open
|
|
io = File.open "/dev/null", File::RDWR, 0
|
|
$stdin.reopen io
|
|
$stdout.reopen io
|
|
$stderr.reopen io
|
|
end
|
|
|
|
return 0
|
|
end
|
|
|
|
def self.exec(*args)
|
|
Rubinius::Mirror::Process.exec(*args)
|
|
end
|
|
|
|
def self.spawn(*args)
|
|
Rubinius::Mirror::Process.spawn(*args)
|
|
end
|
|
|
|
# TODO: Should an error be raised on ECHILD? --rue
|
|
#
|
|
# TODO: This operates on the assumption that waiting on
|
|
# the event consumes very little resources. If this
|
|
# is not the case, the check should be made WNOHANG
|
|
# and called periodically.
|
|
#
|
|
def self.detach(pid)
|
|
raise ArgumentError, "Only positive pids may be detached" unless pid > 0
|
|
|
|
thread = Thread.new { Process.wait pid; $? }
|
|
thread[:pid] = pid
|
|
def thread.pid; self[:pid] end
|
|
|
|
thread
|
|
end
|
|
|
|
def self.coerce_rlimit_resource(resource)
|
|
case resource
|
|
when Integer
|
|
return resource
|
|
when Symbol, String
|
|
# do nothing
|
|
else
|
|
unless r = Rubinius::Type.check_convert_type(resource, String, :to_str)
|
|
return Rubinius::Type.coerce_to resource, Integer, :to_int
|
|
end
|
|
|
|
resource = r
|
|
end
|
|
|
|
constant = "RLIMIT_#{resource}"
|
|
unless const_defined? constant
|
|
raise ArgumentError, "invalid resource name: #{constant}"
|
|
end
|
|
const_get constant
|
|
end
|
|
|
|
class << self
|
|
private :coerce_rlimit_resource
|
|
end
|
|
|
|
#--
|
|
# TODO: Most of the fields aren't implemented yet.
|
|
# TODO: Also, these objects should only need to be constructed by
|
|
# Process.wait and family.
|
|
#++
|
|
|
|
class Status
|
|
|
|
attr_reader :termsig
|
|
attr_reader :stopsig
|
|
|
|
def initialize(pid=nil, status=nil, termsig=nil, stopsig=nil)
|
|
@pid = pid
|
|
@status = status
|
|
@termsig = termsig
|
|
@stopsig = stopsig
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def exitstatus
|
|
@status
|
|
end
|
|
|
|
def to_i
|
|
@status
|
|
end
|
|
|
|
def to_s
|
|
@status.to_s
|
|
end
|
|
|
|
def &(num)
|
|
@status & num
|
|
end
|
|
|
|
def ==(other)
|
|
other = other.to_i if other.kind_of? Process::Status
|
|
@status == other
|
|
end
|
|
|
|
def >>(num)
|
|
@status >> num
|
|
end
|
|
|
|
def coredump?
|
|
false
|
|
end
|
|
|
|
def exited?
|
|
@status != nil
|
|
end
|
|
|
|
def pid
|
|
@pid
|
|
end
|
|
|
|
def signaled?
|
|
@termsig != nil
|
|
end
|
|
|
|
def stopped?
|
|
@stopsig != nil
|
|
end
|
|
|
|
def success?
|
|
if exited?
|
|
@status == 0
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
end
|
|
|
|
module Sys
|
|
class << self
|
|
def getegid
|
|
ret = FFI::Platform::POSIX.getegid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def geteuid
|
|
ret = FFI::Platform::POSIX.geteuid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def getgid
|
|
ret = FFI::Platform::POSIX.getgid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def getuid
|
|
ret = FFI::Platform::POSIX.getuid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def issetugid
|
|
raise "not implemented"
|
|
end
|
|
|
|
def setgid(gid)
|
|
gid = Rubinius::Type.coerce_to gid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setgid gid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def setuid(uid)
|
|
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setuid uid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def setegid(egid)
|
|
egid = Rubinius::Type.coerce_to egid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setegid egid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def seteuid(euid)
|
|
euid = Rubinius::Type.coerce_to euid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.seteuid euid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def setrgid(rgid)
|
|
setregid(rgid, -1)
|
|
end
|
|
|
|
def setruid(ruid)
|
|
setreuid(ruid, -1)
|
|
end
|
|
|
|
def setregid(rid, eid)
|
|
rid = Rubinius::Type.coerce_to rid, Integer, :to_int
|
|
eid = Rubinius::Type.coerce_to eid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setregid rid, eid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def setreuid(rid, eid)
|
|
rid = Rubinius::Type.coerce_to rid, Integer, :to_int
|
|
eid = Rubinius::Type.coerce_to eid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setreuid rid, eid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def setresgid(rid, eid, sid)
|
|
rid = Rubinius::Type.coerce_to rid, Integer, :to_int
|
|
eid = Rubinius::Type.coerce_to eid, Integer, :to_int
|
|
sid = Rubinius::Type.coerce_to sid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setresgid rid, eid, sid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
|
|
def setresuid(rid, eid, sid)
|
|
rid = Rubinius::Type.coerce_to rid, Integer, :to_int
|
|
eid = Rubinius::Type.coerce_to eid, Integer, :to_int
|
|
sid = Rubinius::Type.coerce_to sid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setresuid rid, eid, sid
|
|
Errno.handle if ret == -1
|
|
nil
|
|
end
|
|
end
|
|
end
|
|
|
|
module UID
|
|
class << self
|
|
def change_privilege(uid)
|
|
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setreuid(uid, uid)
|
|
Errno.handle if ret == -1
|
|
uid
|
|
end
|
|
|
|
def eid
|
|
ret = FFI::Platform::POSIX.geteuid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def eid=(uid)
|
|
uid = Rubinius::Type.coerce_to uid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.seteuid(uid)
|
|
Errno.handle if ret == -1
|
|
uid
|
|
end
|
|
alias_method :grant_privilege, :eid=
|
|
|
|
def re_exchange
|
|
real = FFI::Platform::POSIX.getuid
|
|
Errno.handle if real == -1
|
|
eff = FFI::Platform::POSIX.geteuid
|
|
Errno.handle if eff == -1
|
|
ret = FFI::Platform::POSIX.setreuid(eff, real)
|
|
Errno.handle if ret == -1
|
|
eff
|
|
end
|
|
|
|
def re_exchangeable?
|
|
true
|
|
end
|
|
|
|
def rid
|
|
ret = FFI::Platform::POSIX.getuid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def sid_available?
|
|
true
|
|
end
|
|
|
|
def switch
|
|
eff = re_exchange
|
|
if block_given?
|
|
ret = yield
|
|
re_exchange
|
|
return ret
|
|
else
|
|
return eff
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
module GID
|
|
class << self
|
|
def change_privilege(gid)
|
|
gid = Rubinius::Type.coerce_to gid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setregid(gid, gid)
|
|
Errno.handle if ret == -1
|
|
gid
|
|
end
|
|
|
|
def eid
|
|
ret = FFI::Platform::POSIX.getegid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def eid=(gid)
|
|
gid = Rubinius::Type.coerce_to gid, Integer, :to_int
|
|
|
|
ret = FFI::Platform::POSIX.setegid(gid)
|
|
Errno.handle if ret == -1
|
|
gid
|
|
end
|
|
alias_method :grant_privilege, :eid=
|
|
|
|
def re_exchange
|
|
real = FFI::Platform::POSIX.getgid
|
|
Errno.handle if real == -1
|
|
eff = FFI::Platform::POSIX.getegid
|
|
Errno.handle if eff == -1
|
|
ret = FFI::Platform::POSIX.setregid(eff, real)
|
|
Errno.handle if ret == -1
|
|
eff
|
|
end
|
|
|
|
def re_exchangeable?
|
|
true
|
|
end
|
|
|
|
def rid
|
|
ret = FFI::Platform::POSIX.getgid
|
|
Errno.handle if ret == -1
|
|
ret
|
|
end
|
|
|
|
def sid_available?
|
|
true
|
|
end
|
|
|
|
def switch
|
|
eff = re_exchange
|
|
if block_given?
|
|
ret = yield
|
|
re_exchange
|
|
return ret
|
|
else
|
|
return eff
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|