VFS: select(2) fixes
- check each file descriptor's open access mode (filp_mode); - treat an error returned by a character driver as a select error; - check all filps in each set before finishing select; - do not copy back file descriptor sets if an error occurred; - remove the hardcoded list of supported character major devices, since all drivers should now be capable of responding properly; - add tests to test40 and fix its error count aggregation. Change-Id: I57ef58d3afb82640fc50b59c859ee4b25f02db17
This commit is contained in:
@@ -67,7 +67,7 @@ MINIX_TESTS+= \
|
||||
PROGS+= test${t}
|
||||
.endfor
|
||||
|
||||
PROGS+= t10a t11a t11b t40a t40b t40c t40d t40e t40f t60a t60b \
|
||||
PROGS+= t10a t11a t11b t40a t40b t40c t40d t40e t40f t40g t60a t60b \
|
||||
t67a t67b t68a t68b
|
||||
|
||||
SCRIPTS+= run testinterp.sh testsh1.sh testsh2.sh testmfs.sh testisofs.sh
|
||||
|
||||
51
test/t40c.c
51
test/t40c.c
@@ -60,26 +60,28 @@ static void open_terminal(int *child_fd, int *parent_fd) {
|
||||
}
|
||||
|
||||
static int do_child(int terminal) {
|
||||
struct timeval tv;
|
||||
|
||||
/* Going to sleep for two seconds to allow the parent proc to get ready */
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
sleep(2);
|
||||
|
||||
/* Try to write. Doesn't matter how many bytes we actually send. */
|
||||
(void) write(terminal, SENDSTRING, strlen(SENDSTRING));
|
||||
close(terminal);
|
||||
|
||||
/* Wait for another second to allow the parent to process incoming data */
|
||||
tv.tv_usec = 1000000;
|
||||
(void) select(0,NULL, NULL, NULL, &tv);
|
||||
sleep(1);
|
||||
|
||||
/* Write some more, and wait some more. */
|
||||
(void) write(terminal, SENDSTRING, strlen(SENDSTRING));
|
||||
|
||||
sleep(1);
|
||||
|
||||
close(terminal);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int do_parent(int child, int terminal) {
|
||||
fd_set fds_read, fds_write, fds_error;
|
||||
int retval;
|
||||
fd_set fds_read, fds_read2, fds_write, fds_error;
|
||||
int retval, terminal2, highest;
|
||||
char buf[256];
|
||||
|
||||
/* Clear bit masks */
|
||||
FD_ZERO(&fds_read); FD_ZERO(&fds_write); FD_ZERO(&fds_error);
|
||||
@@ -96,7 +98,6 @@ static int do_parent(int child, int terminal) {
|
||||
|
||||
if(retval != 1) em(1, "incorrect amount of ready file descriptors");
|
||||
|
||||
|
||||
if(FD_ISSET(terminal, &fds_read)) em(2, "read should NOT be set");
|
||||
if(!FD_ISSET(terminal, &fds_write)) em(3, "write should be set");
|
||||
if(FD_ISSET(terminal, &fds_error)) em(4, "error should NOT be set");
|
||||
@@ -110,7 +111,6 @@ static int do_parent(int child, int terminal) {
|
||||
if(!FD_ISSET(terminal, &fds_read)) em(6, "read should be set");
|
||||
if(FD_ISSET(terminal, &fds_error)) em(7, "error should not be set");
|
||||
|
||||
|
||||
FD_ZERO(&fds_read); FD_ZERO(&fds_error);
|
||||
FD_SET(terminal, &fds_write);
|
||||
retval = select(terminal+1, NULL, &fds_write, NULL, NULL);
|
||||
@@ -118,6 +118,33 @@ static int do_parent(int child, int terminal) {
|
||||
* immediately with fd set in fds_write. */
|
||||
if(retval != 1) em(8, "incorrect amount or ready file descriptors");
|
||||
|
||||
/* See if selecting on the same object with two different fds results in both
|
||||
* fds being returned as ready, immediately.
|
||||
*/
|
||||
terminal2 = dup(terminal);
|
||||
if (terminal2 < 0) em(9, "unable to dup file descriptor");
|
||||
|
||||
FD_ZERO(&fds_read);
|
||||
FD_SET(terminal, &fds_read);
|
||||
FD_SET(terminal2, &fds_read);
|
||||
fds_read2 = fds_read;
|
||||
highest = terminal > terminal2 ? terminal : terminal2;
|
||||
|
||||
retval = select(highest+1, &fds_read, NULL, NULL, NULL);
|
||||
if (retval != 2) em(10, "incorrect amount of ready file descriptors");
|
||||
if (!FD_ISSET(terminal, &fds_read)) em(11, "first fd missing from set");
|
||||
if (!FD_ISSET(terminal2, &fds_read)) em(12, "second fd missing from set");
|
||||
|
||||
/* Empty the buffer. */
|
||||
if (read(terminal, buf, sizeof(buf)) <= 0) em(13, "unable to read data");
|
||||
|
||||
/* Repeat the test, now with a delay. */
|
||||
retval = select(highest+1, &fds_read2, NULL, NULL, NULL);
|
||||
if (retval != 2) em(10, "incorrect amount of ready file descriptors");
|
||||
if (!FD_ISSET(terminal, &fds_read2)) em(11, "first fd missing from set");
|
||||
if (!FD_ISSET(terminal2, &fds_read2)) em(12, "second fd missing from set");
|
||||
|
||||
close(terminal2);
|
||||
close(terminal);
|
||||
waitpid(child, &retval, 0);
|
||||
exit(errct);
|
||||
|
||||
52
test/t40g.c
Normal file
52
test/t40g.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* t40g.c
|
||||
*
|
||||
* Test select on character driver that does not support select
|
||||
*
|
||||
* We use /dev/zero for this right now. If the memory driver ever implements
|
||||
* select support, this test should be changed to use another character driver.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
fd_set set;
|
||||
int fd, retval;
|
||||
|
||||
/* Get subtest number */
|
||||
if (argc != 2 || sscanf(argv[1], "%d", &subtest) != 1) {
|
||||
printf("Usage: %s subtest_no\n", argv[0]);
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a select on /dev/zero, with the expectation that it will fail
|
||||
* with an EBADF error code.
|
||||
*/
|
||||
fd = open("/dev/zero", O_RDONLY);
|
||||
if (fd < 0) em(1, "unable to open /dev/zero");
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(fd, &set);
|
||||
|
||||
retval = select(fd + 1, &set, NULL, NULL, NULL);
|
||||
if (retval != -1) em(2, "select call was expected to fail");
|
||||
if (errno != EBADF) em(3, "error code other than EBADF returned");
|
||||
if (!FD_ISSET(fd, &set)) em(4, "file descriptor set was modified");
|
||||
|
||||
exit(errct);
|
||||
}
|
||||
@@ -16,9 +16,9 @@ int max_error = 5;
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *tests[] = {"t40a", "t40b", "t40c", "t40d", "t40e", "t40f"};
|
||||
char *tests[] = {"t40a", "t40b", "t40c", "t40d", "t40e", "t40f", "t40g"};
|
||||
char copy_command[8+PATH_MAX+1];
|
||||
int no_tests, i, forkres, status = 0, errorct = 0;
|
||||
int no_tests, i, forkres, status = 0;
|
||||
|
||||
no_tests = sizeof(tests) / sizeof(char *);
|
||||
|
||||
@@ -39,7 +39,7 @@ int main(int argc, char **argv) {
|
||||
exit(-2);
|
||||
} else if(forkres > 0) { /* Parent */
|
||||
if(waitpid(forkres, &status, 0) > 0 && WEXITSTATUS(status) < 20) {
|
||||
errorct += WEXITSTATUS(status); /* Count errors */
|
||||
errct += WEXITSTATUS(status); /* Count errors */
|
||||
}
|
||||
status = 0; /* Reset */
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user