mirror of
https://github.com/uselessd/alcove.git
synced 2026-04-15 17:25:33 +00:00
Use atoms to represent signals
Accept and return signals as names. For example, if a signal is trapped,
the process will receive:
{signal,'SIGCHLD'}
Versus:
{signal,17} % on linux
Benefits:
* similar to the way errno is returned, e.g., {errno,enametoolong}
* better portability: integer values differ by platform
* library user does not need lookup the signal value before calling
sigaction/3,4 or pattern matching the process mailbox
Problems:
* sigaction/3,4 will throw badarg if the name is unknown
Probably it should return an error ({error,einval}).
* not all functions dealing with signals have been changed to use atoms,
e.g., kill/3,4
* all functions with mapping of constants -> integers should take
constants:
clone_define
mount_define
file_define
prctl_define
rlimit_define
syscall_define
If this is done, alcove:define/2,3 and the *_define/*_constant functions
should be removed.
* should the constants be upper or lower case atoms?
atoms are typically lowercased, e.g., {error,ebadf} not
{error,'EBADF'}
For example:
PR_SET_PDEATHSIG -> pr_set_pdeathsig
* if the interface accepts constants, should support for integers be
removed?
1. No way to pass in a "raw" signum if the signal does not have a name
2. Signals without a name will be sent to the process mailbox as:
{signal,unknown}
If the caller has trapped 58 and 59, there won't be a way to
distinguish these signals.
This commit is contained in:
18
README.md
18
README.md
@@ -225,9 +225,7 @@ true
|
||||
|
||||
% If we check the parent for events, we can see the child has exited
|
||||
10> alcove:event(P).
|
||||
{signal,17}
|
||||
11> alcove:signal_constant(P, 17).
|
||||
'SIGCHLD'
|
||||
{signal,'SIGCHLD'}
|
||||
```
|
||||
|
||||
Creating a Container Using Linux Namespaces
|
||||
@@ -440,14 +438,12 @@ probably confuse the process.
|
||||
|
||||
environ(7) : return the process environment variables
|
||||
|
||||
event(Drv) -> {Tag, Val} | false
|
||||
event(Drv, Pids) -> {Tag, Val} | false
|
||||
|
||||
Types Tag = signal
|
||||
Val = integer()
|
||||
event(Drv) -> term()
|
||||
event(Drv, Pids) -> term()
|
||||
|
||||
event/1,2 is used to retrieve async messages returned from the
|
||||
port, such as trapped signals.
|
||||
port, such as trapped signals, the exit status or the termination
|
||||
signal.
|
||||
|
||||
execve(Drv, Arg0, [Arg0, Args], Env) -> ok | {error, posix()}
|
||||
execve(Drv, Pids, Arg0, [Arg0, Args], Env) -> ok | {error, posix()}
|
||||
@@ -542,7 +538,7 @@ probably confuse the process.
|
||||
|
||||
Sets the maximum length of the fork path.
|
||||
|
||||
termisg : 1 | 0 : 0
|
||||
termsig : 1 | 0 : 0
|
||||
|
||||
If a child process exits because of a signal, notify
|
||||
the controlling Erlang process.
|
||||
@@ -796,7 +792,7 @@ probably confuse the process.
|
||||
sigaction(Drv, Signum, Handler) -> ok | {error, posix()}
|
||||
sigaction(Drv, Pids, Signum, Handler) -> ok | {error, posix()}
|
||||
|
||||
Types Signum = integer()
|
||||
Types Signum = integer() | atom()
|
||||
Handler = dfl | ign | trap
|
||||
|
||||
sigaction(2) : set process behaviour for signals
|
||||
|
||||
@@ -536,8 +536,8 @@ specs() ->
|
||||
-spec setuid(alcove_drv:ref(),non_neg_integer()) -> 'ok' | {'error', file:posix()}.
|
||||
-spec setuid(alcove_drv:ref(),fork_path(),non_neg_integer()) -> 'ok' | {'error', file:posix()}.
|
||||
|
||||
-spec sigaction(alcove_drv:ref(),integer(),atom()) -> 'ok' | {'error', file:posix()}.
|
||||
-spec sigaction(alcove_drv:ref(),fork_path(),integer(),atom()) -> 'ok' | {'error', file:posix()}.
|
||||
-spec sigaction(alcove_drv:ref(),integer() | atom(),atom()) -> 'ok' | {'error', file:posix()}.
|
||||
-spec sigaction(alcove_drv:ref(),fork_path(),integer() | atom(),atom()) -> 'ok' | {'error', file:posix()}.
|
||||
|
||||
-spec signal_constant(alcove_drv:ref(),non_neg_integer()) -> 'unknown' | atom().
|
||||
-spec signal_constant(alcove_drv:ref(),fork_path(),non_neg_integer()) -> 'unknown' | atom().
|
||||
|
||||
@@ -583,7 +583,7 @@ exited_pid(alcove_state_t *ap, alcove_child_t *c, void *arg1, void *arg2)
|
||||
if (WIFSIGNALED(*status) && (ap->opt & alcove_opt_termsig)) {
|
||||
ALCOVE_TUPLE2(t, &index,
|
||||
"termsig",
|
||||
ei_encode_long(t, &index, WTERMSIG(*status))
|
||||
alcove_signal_name(t, sizeof(t), &index, WTERMSIG(*status))
|
||||
);
|
||||
|
||||
if (alcove_call_fake_reply(c->pid, ALCOVE_MSG_EVENT, t, index) < 0)
|
||||
@@ -745,7 +745,7 @@ alcove_handle_signal(alcove_state_t *ap) {
|
||||
|
||||
ALCOVE_TUPLE2(reply, &index,
|
||||
"signal",
|
||||
ei_encode_long(reply, &index, signum)
|
||||
alcove_signal_name(reply, sizeof(reply), &index, signum)
|
||||
);
|
||||
|
||||
if (alcove_call_reply(ALCOVE_MSG_EVENT, reply, index) < 0)
|
||||
|
||||
@@ -162,6 +162,8 @@ int pid_foreach(alcove_state_t *ap, pid_t pid, void *arg1, void *arg2,
|
||||
int pid_equal(pid_t p1, pid_t p2);
|
||||
int pid_not_equal(pid_t p1, pid_t p2);
|
||||
|
||||
ssize_t alcove_signal_name(char *, size_t, int *, int);
|
||||
|
||||
int alcove_get_type(const char *, size_t, const int *, int *, int *);
|
||||
int alcove_decode_int(const char *, size_t, int *, int *);
|
||||
int alcove_decode_uint(const char *, size_t, int *, u_int32_t *);
|
||||
|
||||
@@ -161,3 +161,10 @@ alcove_signal_constant(alcove_state_t *ap, const char *arg, size_t len,
|
||||
|
||||
return rindex;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
alcove_signal_name(char *buf, size_t len, int *index, int signum)
|
||||
{
|
||||
return alcove_encode_constant(buf, len, index, signum,
|
||||
alcove_signal_constants);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{application, alcove,
|
||||
[
|
||||
{description, "Erlang application container/sandbox"},
|
||||
{vsn, "0.8.1"},
|
||||
{vsn, "0.9.0"},
|
||||
{registered, []},
|
||||
{applications, [
|
||||
kernel,
|
||||
|
||||
@@ -62,8 +62,6 @@ stop(#state{pid = Drv}) ->
|
||||
alcove_drv:stop(Drv).
|
||||
|
||||
kill(#state{pid = Drv}) ->
|
||||
SIGSYS = alcove:define(Drv, 'SIGSYS'),
|
||||
|
||||
{ok, Pid} = alcove:fork(Drv),
|
||||
enforce(Drv, [Pid], ?BPF_STMT(?BPF_RET+?BPF_K, ?SECCOMP_RET_KILL)),
|
||||
% Allowed: cached by process
|
||||
@@ -80,7 +78,7 @@ kill(#state{pid = Drv}) ->
|
||||
|
||||
[
|
||||
?_assertEqual(Pid, Reply0),
|
||||
?_assertEqual({termsig, SIGSYS}, Event),
|
||||
?_assertEqual({termsig, 'SIGSYS'}, Event),
|
||||
?_assertEqual({error, esrch}, Reply3)
|
||||
].
|
||||
|
||||
@@ -99,10 +97,8 @@ allow(#state{pid = Drv}) ->
|
||||
].
|
||||
|
||||
trap(#state{pid = Drv}) ->
|
||||
SIGSYS = alcove:define(Drv, 'SIGSYS'),
|
||||
|
||||
{ok, Pid} = alcove:fork(Drv),
|
||||
ok = alcove:sigaction(Drv, [Pid], SIGSYS, trap),
|
||||
ok = alcove:sigaction(Drv, [Pid], 'SIGSYS', trap),
|
||||
|
||||
enforce(Drv, [Pid], ?BPF_STMT(?BPF_RET+?BPF_K, ?SECCOMP_RET_TRAP)),
|
||||
|
||||
@@ -125,7 +121,7 @@ trap(#state{pid = Drv}) ->
|
||||
[
|
||||
?_assertEqual(Pid, Reply0),
|
||||
?_assertEqual(true, Reply1),
|
||||
?_assertEqual({signal, SIGSYS}, Event),
|
||||
?_assertEqual({signal, 'SIGSYS'}, Event),
|
||||
?_assertEqual(ok, Reply3)
|
||||
].
|
||||
|
||||
|
||||
@@ -78,8 +78,7 @@ start() ->
|
||||
|
||||
{ok, Drv} = alcove_drv:start([{exec, Exec}, {maxchild, 8}]),
|
||||
|
||||
SIGCHLD = alcove:define(Drv, 'SIGCHLD'),
|
||||
ok = alcove:sigaction(Drv, SIGCHLD, trap),
|
||||
ok = alcove:sigaction(Drv, 'SIGCHLD', trap),
|
||||
|
||||
case {Use_fork, os:type()} of
|
||||
{false, {unix,linux} = OS} ->
|
||||
@@ -399,14 +398,14 @@ badpid(#state{pid = Drv}) ->
|
||||
signal(#state{pid = Drv}) ->
|
||||
{ok, Child1} = alcove:fork(Drv),
|
||||
|
||||
TERM = alcove:signal_define(Drv, 'SIGTERM'),
|
||||
SIGTERM = alcove:signal_define(Drv, 'SIGTERM'),
|
||||
|
||||
SA0 = alcove:sigaction(Drv, [Child1], TERM, ign),
|
||||
Kill0 = alcove:kill(Drv, Child1, TERM),
|
||||
SA0 = alcove:sigaction(Drv, [Child1], SIGTERM, ign),
|
||||
Kill0 = alcove:kill(Drv, Child1, SIGTERM),
|
||||
Pid0 = alcove:getpid(Drv, [Child1]),
|
||||
|
||||
SA1 = alcove:sigaction(Drv, [Child1], TERM, dfl),
|
||||
Kill1 = alcove:kill(Drv, Child1, TERM),
|
||||
SA1 = alcove:sigaction(Drv, [Child1], 'SIGTERM', dfl),
|
||||
Kill1 = alcove:kill(Drv, Child1, SIGTERM),
|
||||
waitpid(Drv, [], Child1),
|
||||
alcove:kill(Drv, Child1, 0),
|
||||
Search = alcove:kill(Drv, Child1, 0),
|
||||
@@ -613,9 +612,8 @@ getenv(Name, Default) ->
|
||||
end.
|
||||
|
||||
waitpid(Drv, Pids, Child) ->
|
||||
SIGCHLD = alcove:signal_define(Drv, 'SIGCHLD'),
|
||||
case alcove:event(Drv, Pids, 5000) of
|
||||
{signal, SIGCHLD} ->
|
||||
{signal, 'SIGCHLD'} ->
|
||||
waitpid_1(Drv, Pids, Child);
|
||||
false ->
|
||||
false
|
||||
|
||||
Reference in New Issue
Block a user