Check for invalid fd's

Add a test for closing stdio. The final test (closing stdin) is marked
as passing if {error,esrch} or {error,ebadf} is returned because there
is a race condition: the event loop may not have noticed the fd is
closed depending on how quickly the test is run.
This commit is contained in:
Michael Santos
2014-04-21 12:23:29 -04:00
parent 78fa3f077a
commit f4c320ba50
2 changed files with 30 additions and 4 deletions

View File

@@ -220,7 +220,7 @@ alcove_event_loop(alcove_state_t *ap)
}
}
if (fds[STDIN_FILENO].revents & (POLLIN|POLLERR|POLLHUP)) {
if (fds[STDIN_FILENO].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) {
switch (alcove_stdin(ap)) {
case -1:
erl_err_sys("alcove_stdin");
@@ -663,7 +663,7 @@ read_from_pid(alcove_state_t *ap, alcove_child_t *c, void *arg1, void *arg2)
{
struct pollfd *fds = arg1;
if (c->fdctl > -1 && (fds[c->fdctl].revents & (POLLIN|POLLERR|POLLHUP))) {
if (c->fdctl > -1 && (fds[c->fdctl].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL))) {
unsigned char buf;
ssize_t n;
@@ -679,7 +679,7 @@ read_from_pid(alcove_state_t *ap, alcove_child_t *c, void *arg1, void *arg2)
}
}
if (c->fdout > -1 && (fds[c->fdout].revents & (POLLIN|POLLERR|POLLHUP))) {
if (c->fdout > -1 && (fds[c->fdout].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL))) {
switch (alcove_child_stdio(c->fdout, ap->depth,
c, ALCOVE_MSG_TYPE(c))) {
case -1:
@@ -692,7 +692,7 @@ read_from_pid(alcove_state_t *ap, alcove_child_t *c, void *arg1, void *arg2)
}
}
if (c->fderr > -1 && (fds[c->fderr].revents & (POLLIN|POLLERR|POLLHUP))) {
if (c->fderr > -1 && (fds[c->fderr].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL))) {
switch (alcove_child_stdio(c->fderr, ap->depth,
c, ALCOVE_MSG_STDERR)) {
case -1:

View File

@@ -59,6 +59,7 @@ run(State) ->
portstress(State),
forkstress(State),
forkchain(State),
eof(State),
prctl(State),
execvp(State),
stdout(State),
@@ -398,6 +399,31 @@ forkchain(#state{port = Port}) ->
?_assertEqual(Pid, Child4).
eof(#state{port = Port}) ->
{ok, Child} = alcove:fork(Port),
{ok, Child0} = alcove:fork(Port, [Child]),
ok = alcove:eof(Port, [Child,Child0], stderr),
Reply0 = alcove:eof(Port, [Child,Child0], stderr),
ok = alcove:eof(Port, [Child,Child0], stdout),
Reply1 = alcove:eof(Port, [Child,Child0], stdout),
ok = alcove:eof(Port, [Child,Child0]),
Reply2 = case alcove:eof(Port, [Child,Child0]) of
{error,esrch} -> ok;
{error,ebadf} -> ok;
N -> N
end,
alcove:exit(Port, [Child], 0),
[
?_assertEqual({error,ebadf}, Reply0),
?_assertEqual({error,ebadf}, Reply1),
?_assertEqual(ok, Reply2)
].
prctl(#state{os = {unix,linux}, port = Port}) ->
{ok, Fork} = alcove:fork(Port),