{"id":18151196,"url":"https://github.com/msantos/perc","last_synced_at":"2025-09-12T22:49:50.556Z","repository":{"id":3760763,"uuid":"4836895","full_name":"msantos/perc","owner":"msantos","description":"Erlang interface for controlling Unix processes","archived":false,"fork":false,"pushed_at":"2023-05-28T10:54:31.000Z","size":130,"stargazers_count":16,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T03:37:03.760Z","etag":null,"topics":["signal","system-programming"],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/msantos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-06-29T20:33:49.000Z","updated_at":"2024-08-22T22:11:06.000Z","dependencies_parsed_at":"2022-08-17T23:00:40.153Z","dependency_job_id":"e563ab60-8022-4e70-a86e-4d83cfa1a32b","html_url":"https://github.com/msantos/perc","commit_stats":{"total_commits":48,"total_committers":1,"mean_commits":48.0,"dds":0.0,"last_synced_commit":"212e4a6a89624e5d533d8d995cbdc0c00e68a7f4"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fperc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fperc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fperc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msantos%2Fperc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/msantos","download_url":"https://codeload.github.com/msantos/perc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251354541,"owners_count":21576212,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["signal","system-programming"],"created_at":"2024-11-02T01:06:53.798Z","updated_at":"2025-04-28T17:28:13.967Z","avatar_url":"https://github.com/msantos.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"perc is an Erlang interface for controlling Unix processes.\n\n## COMPILING\n\n```\nrebar3 do compile, eunit\n```\n\n## EXPORTS\n\n### perc\n\n```\nkill(Pid, Signal) -\u003e ok | {error, posix()}\n\n    Types   Pid = integer()\n            Signal = integer() | atom()\n\n    Send a signal to a Unix process.\n\n    Process IDs and signals are signed 32-bit integers. A signal\n    can also be the lower cased signal name as an atom.\n\n    Sending a signal to PID 0 will send the signal to the Erlang VM.\n\ngetuid() -\u003e uint32_t()\n\n    See getuid(2).\n\n    Get user identity.\n\ngetgid() -\u003e uint32_t()\n\n    See getgid(2).\n\n    Get group identity.\n\ngeteuid() -\u003e uint32_t()\n\n    See geteuid(2).\n\n    Get effective user id.\n\ngetegid() -\u003e uint32_t()\n\n    See getegid(2).\n\n    Get effective group id.\n\ngetgroups() -\u003e [uint32_t()]\n\n    See getgroups(2).\n\n    Retrieve the list of supplementary groups.\n\nsetgroups([uint32_t()]) -\u003e ok | {error, posix()}\n\n    See setgroups(2).\n\n    Set the list of supplementary groups.\n\nsetresuid(Ruid, Euid, Suid) -\u003e ok | {error, posix()}\n\n    Types   Ruid = uint32_t()\n            Euid = uint32_t()\n            Suid = uint32_t()\n\n    See setresuid(2).\n\n    Set real, effective and saved user id.\n\nsetresgid(Rgid, Egid, Sgid) -\u003e ok | {error, posix()}\n\n    Types   Rgid = uint32_t()\n            Egid = uint32_t()\n            Sgid = uint32_t()\n\n    See setresgid(2).\n\n    Set real, effective and saved group id.\n\ngetpriority(Which, Who) -\u003e {ok, integer()} | {error, posix()}\n\n    Types   Which = integer()\n            Who = integer()\n\n    See getpriority(2).\n\n    Get the priority (the \"nice\" value) of processes by pid, process\n    group or user.\n\nsetpriority(Which, Who, Prio) -\u003e ok | {error, posix()}\n\n    Types   Which = integer()\n            Who = integer()\n            Prio = integer()\n\n    See setpriority(2).\n\n    Set the priority (the \"nice\" value) of processes by pid, process\n    group or user.\n\nrenice(Type, Prio) -\u003e ok | {error, posix()}\n\n    Types   Type = {Which, Who}\n            Which = pid | pgrp | user\n            Who = integer()\n            Prio = integer() | string()\n\n    Convenience wrapper around getpriority/2 and setpriority/3,\n    similar to renice(1).\n\n    WARNING: renice/2 makes successive calls to getpriority/2 and\n    setpriority/3. Since this sequence is not atomic, the priority\n    may change between calls or the process may have been terminated.\n\n    Sets the priority of a process or processes by pid, pgroup or\n    user. The new priority may be an integer or a list containing a\n    relative priority, indicated by using a \"+\" or \"-\". For example,\n    using \"+10\" will increase the niceness of the process by 10.\n\nprlimit(Pid, Resource, NewLimit, OldLimit) -\u003e {ok, NewLimit1, OldLimit1} | {error, Error}\n\n    Types   Pid = integer()\n            Resource = integer()\n                | rlimit_cpu\n                | rlimit_fsize\n                | rlimit_data\n                | rlimit_stack\n                | rlimit_core\n                | rlimit_rss\n                | rlimit_nproc\n                | rlimit_nofile\n                | rlimit_ofile\n                | rlimit_memlock\n                | rlimit_as\n                | rlimit_locks\n                | rlimit_sigpending\n                | rlimit_msgqueue\n                | rlimit_nice\n                | rlimit_rtprio\n                | rlimit_rttime\n                | rlimit_nlimits\n                | rlim_infinity\n            NewLimit = NewLimit1 = \u003c\u003c\u003e\u003e | binary()\n            OldLimit = OldLimit1 = \u003c\u003c\u003e\u003e | binary()\n            Error = unsupported | posix()\n\n    Linux only: on other platforms, {error, unsupported} will be\n    returned to the caller.\n\n    Set or retrieve process limits for a process. Passing in an\n    empty binary for NewLimit or OldLimit indicates the caller is\n    not interested in these values.\n\n    The binary size of NewLimit/OldLimit must otherwise match the size\n    of a struct rlimit for the platform. struct rlimit is usually\n    composed of two 8 byte values in native format. To retrieve the\n    current settings, pass in a zeroed 16 byte value.\n\ngetrlimit(Resource) -\u003e {ok, Limit} | {error, Error}\n\n    Types Resource = integer() | rlimit()\n          Error = posix()\n\n    Get process limits for beam. See prlimit/4 for a list of the\n    resource atoms.\n\n    The value returned is a struct rlimit:\n\n        1\u003e {ok, \u003c\u003cSoft:8/native-unsigned-integer-unit:8, Hard:8/native-unsigned-integer-unit:8\u003e\u003e} = perc:getrlimit(rlimit_nofile).\n        2\u003e Soft.\n        1024\n        3\u003e Hard.\n        4096\n\nsetrlimit(Resource, Limit) -\u003e {ok, Limit} | {error, Error}\n\n    Types Resource = integer() | rlimit()\n          Error = posix()\n          Limit = binary()\n\n    Set process limits for beam. See prlimit/4 for a list of the\n    resource atoms.\n\numask() -\u003e CurMask\numask(Mask) -\u003e OldMask\n\n    Types   Mask = integer() | list()\n            CurMask = OldMask = integer()\n\n    Sets the file creation mask for beam. The mask may be either\n    an integer or a list representing an octal number, e.g., either\n    8#022 or \"022\".\n\n    The old mask value is returned. To retrieve the current umask,\n    use umask/0 or getumask/0.\n\n    WARNING: umask/0 is destructive: the umask is retrieved by setting\n    the process mask to 0, then re-setting it back to the original\n    mask. Between the successive calls to umask(2), the process\n    mask is 0. An erlang process calling umask/0 concurrently with\n    a process creating a file may have unexpected results.\n\ngetumask() -\u003e CurMask\n\n    Types   CurMask = OldMask = integer()\n\n    Obtain the current process mask by parsing /proc/self/status,\n    avoiding the race condition in umask/0.\n\n    If /proc/self/status does not exist or is not parsable, getumask/0\n    fails back to umask/0.\n```\n\n### perc_signal\n\n*WARNING: support for signalfd(2) is experimental only and is disabled by default.*\n\nTo enable, add `-DHAVE_SIGNALFD` to the rebar.config tuple for your\narchitecture. Some of the signals may be caught by beam. signalfd is\nlikely to work only with a single threaded beam. The interaction between\nsignals and POSIX threads is mysterious.\n\n```\n    start(Signals) -\u003e {ok, pid()} | {error, enomem}\n\n        Types   Signals = [ Signal ]\n                Signal = integer() | Names\n                Names = sighup\n                    | sigint\n                    | sigquit\n                    | sigill\n                    | sigtrap\n                    | sigabrt\n                    | sigbus\n                    | sigfpe\n                    | sigkill\n                    | sigusr1\n                    | sigsegv\n                    | sigusr2\n                    | sigpipe\n                    | sigalrm\n                    | sigterm\n                    | sigstkflt\n                    | sigchld\n                    | sigcont\n                    | sigstop\n                    | sigtstp\n                    | sigttin\n                    | sigttou\n                    | sigurg\n                    | sigxcpu\n                    | sigxfsz\n                    | sigvtalrm\n                    | sigprof\n                    | sigwinch\n                    | sigio\n                    | sigpwr\n                    | sigsys\n                    | sigrtmin\n                    | sigrtmax\n\n    Linux only: on other platforms, {error, unsupported} will be\n    returned to the caller.\n\n    Receive notification when the beam process receives a signal:\n\n        {signal, pid(), #signalfd_siginfo{}}\n\n    The tuple contains the PID of the gen_server and information\n    about the signal. See signalfd(2) for details about the returned\n    data. For example, to match the signal number:\n\n        -include_lib(\"perc/include/perc_signal.hrl\").\n\n        start() -\u003e\n            {ok, Ref} = perc_signal:start([sighup]),\n\n            receive\n                {signal, Ref, #signalfd_siginfo{\n                    ssi_signo = 1,\n                    ssi_pid = Pid,\n                    ssi_uid = UID,\n                    }} -\u003e\n                    error_logger:info_report([\n                        {sending_pid, Pid},\n                        {sending_uid, UID}\n                        ])\n            end.\n\nstop(Ref) -\u003e ok\n\n    Stop the gen_server and close the signalfd file descriptor.\n```\n\n## EXAMPLES\n\n### kill(2)\n\n```\n$ sleep 1000000 \u0026\n[1] 2947\n\n$ erl -pa ebin\n\n1\u003e perc:kill(2947, 9).\nok\n\n2\u003e perc:kill(1, 1).\n{error,eperm}\n\n3\u003e perc:kill(31337, 1).\n{error,esrch}\n```\n\n### prlimit(2)\n\n```\n% Get the current value for rlimit_cpu\n1\u003e perc:prlimit(0, rlimit_cpu, \u003c\u003c\u003e\u003e, \u003c\u003c0:128\u003e\u003e).\n{ok,\u003c\u003c\u003e\u003e,\u003c\u003c\"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\"\u003e\u003e}\n\n% Set RLIMIT_NOFILE (7) on the Erlang VM. Sets the current and max file descriptors\n% to 8.\n1\u003e perc:prlimit(0, 7, \u003c\u003c8:8/native-unsigned-integer-unit:8, 8:8/native-unsigned-integer-unit:8\u003e\u003e, \u003c\u003c\u003e\u003e).\n{ok,\u003c\u003c8,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0\u003e\u003e,\u003c\u003c\u003e\u003e}\n\n2\u003e file:open(\"/etc/passwd\", [read]).\n{ok,\u003c0.39.0\u003e}\n\n3\u003e file:open(\"/etc/passwd\", [read]).\n{error,emfile}\n```\n\n### setpriority(2)/getpriority(2)\n\n```\n% PRIO_PROCESS = 0\n1\u003e perc:getpriority(0, 0).\n{ok, 0}\n\n2\u003e perc:setpriority(0, 0, 10).\nok\n\n3\u003e perc:getpriority(0, 0).\n{ok, 10}\n\n4\u003e perc:renice({pid, 0}, \"-5\").\n{ok, 5}\n```\n\n## TODO\n\n* process lookup\n\n* `atom rlimit_*` constants only supported for 64-bit values\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsantos%2Fperc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmsantos%2Fperc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsantos%2Fperc/lists"}