Skip to content

msantos/perc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

perc is an Erlang interface for controlling Unix processes.

COMPILING

rebar3 do compile, eunit

EXPORTS

perc

kill(Pid, Signal) -> ok | {error, posix()}

    Types   Pid = integer()
            Signal = integer() | atom()

    Send a signal to a Unix process.

    Process IDs and signals are signed 32-bit integers. A signal
    can also be the lower cased signal name as an atom.

    Sending a signal to PID 0 will send the signal to the Erlang VM.

getuid() -> uint32_t()

    See getuid(2).

    Get user identity.

getgid() -> uint32_t()

    See getgid(2).

    Get group identity.

geteuid() -> uint32_t()

    See geteuid(2).

    Get effective user id.

getegid() -> uint32_t()

    See getegid(2).

    Get effective group id.

getgroups() -> [uint32_t()]

    See getgroups(2).

    Retrieve the list of supplementary groups.

setgroups([uint32_t()]) -> ok | {error, posix()}

    See setgroups(2).

    Set the list of supplementary groups.

setresuid(Ruid, Euid, Suid) -> ok | {error, posix()}

    Types   Ruid = uint32_t()
            Euid = uint32_t()
            Suid = uint32_t()

    See setresuid(2).

    Set real, effective and saved user id.

setresgid(Rgid, Egid, Sgid) -> ok | {error, posix()}

    Types   Rgid = uint32_t()
            Egid = uint32_t()
            Sgid = uint32_t()

    See setresgid(2).

    Set real, effective and saved group id.

getpriority(Which, Who) -> {ok, integer()} | {error, posix()}

    Types   Which = integer()
            Who = integer()

    See getpriority(2).

    Get the priority (the "nice" value) of processes by pid, process
    group or user.

setpriority(Which, Who, Prio) -> ok | {error, posix()}

    Types   Which = integer()
            Who = integer()
            Prio = integer()

    See setpriority(2).

    Set the priority (the "nice" value) of processes by pid, process
    group or user.

renice(Type, Prio) -> ok | {error, posix()}

    Types   Type = {Which, Who}
            Which = pid | pgrp | user
            Who = integer()
            Prio = integer() | string()

    Convenience wrapper around getpriority/2 and setpriority/3,
    similar to renice(1).

    WARNING: renice/2 makes successive calls to getpriority/2 and
    setpriority/3. Since this sequence is not atomic, the priority
    may change between calls or the process may have been terminated.

    Sets the priority of a process or processes by pid, pgroup or
    user. The new priority may be an integer or a list containing a
    relative priority, indicated by using a "+" or "-". For example,
    using "+10" will increase the niceness of the process by 10.

prlimit(Pid, Resource, NewLimit, OldLimit) -> {ok, NewLimit1, OldLimit1} | {error, Error}

    Types   Pid = integer()
            Resource = integer()
                | rlimit_cpu
                | rlimit_fsize
                | rlimit_data
                | rlimit_stack
                | rlimit_core
                | rlimit_rss
                | rlimit_nproc
                | rlimit_nofile
                | rlimit_ofile
                | rlimit_memlock
                | rlimit_as
                | rlimit_locks
                | rlimit_sigpending
                | rlimit_msgqueue
                | rlimit_nice
                | rlimit_rtprio
                | rlimit_rttime
                | rlimit_nlimits
                | rlim_infinity
            NewLimit = NewLimit1 = <<>> | binary()
            OldLimit = OldLimit1 = <<>> | binary()
            Error = unsupported | posix()

    Linux only: on other platforms, {error, unsupported} will be
    returned to the caller.

    Set or retrieve process limits for a process. Passing in an
    empty binary for NewLimit or OldLimit indicates the caller is
    not interested in these values.

    The binary size of NewLimit/OldLimit must otherwise match the size
    of a struct rlimit for the platform. struct rlimit is usually
    composed of two 8 byte values in native format. To retrieve the
    current settings, pass in a zeroed 16 byte value.

getrlimit(Resource) -> {ok, Limit} | {error, Error}

    Types Resource = integer() | rlimit()
          Error = posix()

    Get process limits for beam. See prlimit/4 for a list of the
    resource atoms.

    The value returned is a struct rlimit:

        1> {ok, <<Soft:8/native-unsigned-integer-unit:8, Hard:8/native-unsigned-integer-unit:8>>} = perc:getrlimit(rlimit_nofile).
        2> Soft.
        1024
        3> Hard.
        4096

setrlimit(Resource, Limit) -> {ok, Limit} | {error, Error}

    Types Resource = integer() | rlimit()
          Error = posix()
          Limit = binary()

    Set process limits for beam. See prlimit/4 for a list of the
    resource atoms.

umask() -> CurMask
umask(Mask) -> OldMask

    Types   Mask = integer() | list()
            CurMask = OldMask = integer()

    Sets the file creation mask for beam. The mask may be either
    an integer or a list representing an octal number, e.g., either
    8#022 or "022".

    The old mask value is returned. To retrieve the current umask,
    use umask/0 or getumask/0.

    WARNING: umask/0 is destructive: the umask is retrieved by setting
    the process mask to 0, then re-setting it back to the original
    mask. Between the successive calls to umask(2), the process
    mask is 0. An erlang process calling umask/0 concurrently with
    a process creating a file may have unexpected results.

getumask() -> CurMask

    Types   CurMask = OldMask = integer()

    Obtain the current process mask by parsing /proc/self/status,
    avoiding the race condition in umask/0.

    If /proc/self/status does not exist or is not parsable, getumask/0
    fails back to umask/0.

perc_signal

WARNING: support for signalfd(2) is experimental only and is disabled by default.

To enable, add -DHAVE_SIGNALFD to the rebar.config tuple for your architecture. Some of the signals may be caught by beam. signalfd is likely to work only with a single threaded beam. The interaction between signals and POSIX threads is mysterious.

    start(Signals) -> {ok, pid()} | {error, enomem}

        Types   Signals = [ Signal ]
                Signal = integer() | Names
                Names = sighup
                    | sigint
                    | sigquit
                    | sigill
                    | sigtrap
                    | sigabrt
                    | sigbus
                    | sigfpe
                    | sigkill
                    | sigusr1
                    | sigsegv
                    | sigusr2
                    | sigpipe
                    | sigalrm
                    | sigterm
                    | sigstkflt
                    | sigchld
                    | sigcont
                    | sigstop
                    | sigtstp
                    | sigttin
                    | sigttou
                    | sigurg
                    | sigxcpu
                    | sigxfsz
                    | sigvtalrm
                    | sigprof
                    | sigwinch
                    | sigio
                    | sigpwr
                    | sigsys
                    | sigrtmin
                    | sigrtmax

    Linux only: on other platforms, {error, unsupported} will be
    returned to the caller.

    Receive notification when the beam process receives a signal:

        {signal, pid(), #signalfd_siginfo{}}

    The tuple contains the PID of the gen_server and information
    about the signal. See signalfd(2) for details about the returned
    data. For example, to match the signal number:

        -include_lib("perc/include/perc_signal.hrl").

        start() ->
            {ok, Ref} = perc_signal:start([sighup]),

            receive
                {signal, Ref, #signalfd_siginfo{
                    ssi_signo = 1,
                    ssi_pid = Pid,
                    ssi_uid = UID,
                    }} ->
                    error_logger:info_report([
                        {sending_pid, Pid},
                        {sending_uid, UID}
                        ])
            end.

stop(Ref) -> ok

    Stop the gen_server and close the signalfd file descriptor.

EXAMPLES

kill(2)

$ sleep 1000000 &
[1] 2947

$ erl -pa ebin

1> perc:kill(2947, 9).
ok

2> perc:kill(1, 1).
{error,eperm}

3> perc:kill(31337, 1).
{error,esrch}

prlimit(2)

% Get the current value for rlimit_cpu
1> perc:prlimit(0, rlimit_cpu, <<>>, <<0:128>>).
{ok,<<>>,<<"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ">>}

% Set RLIMIT_NOFILE (7) on the Erlang VM. Sets the current and max file descriptors
% to 8.
1> perc:prlimit(0, 7, <<8:8/native-unsigned-integer-unit:8, 8:8/native-unsigned-integer-unit:8>>, <<>>).
{ok,<<8,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0>>,<<>>}

2> file:open("/etc/passwd", [read]).
{ok,<0.39.0>}

3> file:open("/etc/passwd", [read]).
{error,emfile}

setpriority(2)/getpriority(2)

% PRIO_PROCESS = 0
1> perc:getpriority(0, 0).
{ok, 0}

2> perc:setpriority(0, 0, 10).
ok

3> perc:getpriority(0, 0).
{ok, 10}

4> perc:renice({pid, 0}, "-5").
{ok, 5}

TODO

  • process lookup

  • atom rlimit_* constants only supported for 64-bit values

About

Erlang interface for controlling Unix processes

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published