summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/syscalls.c6
-rw-r--r--src/user/app/tests/kernel/fdlimit.c49
-rw-r--r--src/user/app/tests/tests.c1
-rw-r--r--src/user/app/tests/tests.h1
4 files changed, 54 insertions, 3 deletions
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index dc8f9df..1909eb7 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -51,11 +51,10 @@ long _syscall_fork(int flags, handle_t __user *fs_front) {
child = process_fork(process_current, flags);
regs_savereturn(&child->regs, 0);
- if ((flags & FORK_NEWFS) && fs_front) {
+ if (flags & FORK_NEWFS) {
struct handle *h;
handle_t hid = process_handle_init(process_current, HANDLE_FS_FRONT, &h);
if (hid < 0) {
- // TODO test
child->noreap = true;
process_kill(child, -EMFILE);
SYSCALL_RETURN(-EMFILE);
@@ -87,8 +86,9 @@ handle_t _syscall_open(const char __user *path, long len, int flags) {
if (PATH_MAX < len)
SYSCALL_RETURN(-1);
+ // TODO remove this check - it's not worth it w/ threads
if (process_find_free_handle(process_current, 0) < 0)
- SYSCALL_RETURN(-1);
+ SYSCALL_RETURN(-EMFILE);
path_buf = kmalloc(len);
if (!path_buf) goto fail;
diff --git a/src/user/app/tests/kernel/fdlimit.c b/src/user/app/tests/kernel/fdlimit.c
new file mode 100644
index 0000000..d22af13
--- /dev/null
+++ b/src/user/app/tests/kernel/fdlimit.c
@@ -0,0 +1,49 @@
+#include "../tests.h"
+#include <camellia/flags.h>
+#include <errno.h>
+#include <unistd.h>
+
+static void test_fdlimit_pipe(void) {
+ handle_t ends[2];
+ handle_t h[2] = {-1, -1};
+ for (;;) {
+ handle_t cur = _syscall_open("/", 1, OPEN_READ);
+ if (cur == -EMFILE) break;
+ test(cur >= 0);
+ h[0] = h[1];
+ h[1] = cur;
+ }
+ test(h[0] >= 0); /* we need at least two handles */
+
+ test(_syscall_pipe(ends, 0) == -EMFILE);
+ test(_syscall_open("/", 1, OPEN_READ) == -EMFILE);
+
+ close(h[1]);
+ test(_syscall_pipe(ends, 0) == -EMFILE);
+ test(_syscall_open("/", 1, OPEN_READ) == h[1]);
+ test(_syscall_open("/", 1, OPEN_READ) == -EMFILE);
+
+ close(h[0]);
+ close(h[1]);
+ test(_syscall_pipe(ends, 0) == 0);
+}
+
+static void test_fdlimit_fork(void) {
+ for (;;) {
+ handle_t cur = _syscall_open("/", 1, OPEN_READ);
+ if (cur == -EMFILE) break;
+ test(cur >= 0);
+ }
+
+ if (!_syscall_fork(0, NULL)) _syscall_exit(123);
+
+ test(_syscall_fork(FORK_NEWFS, NULL) == -EMFILE);
+ test(_syscall_await() == 123);
+ test(_syscall_await() == ~0);
+}
+
+void r_k_fdlimit(void) {
+ /* all these tests implicitly test if the vfs returns -EMFILE */
+ run_test(test_fdlimit_pipe);
+ run_test(test_fdlimit_fork);
+}
diff --git a/src/user/app/tests/tests.c b/src/user/app/tests/tests.c
index 29733aa..14225ac 100644
--- a/src/user/app/tests/tests.c
+++ b/src/user/app/tests/tests.c
@@ -36,6 +36,7 @@ int forkpipe(FILE **f, handle_t *h) {
int main(void) {
handle_t reader;
if (!forkpipe(&fail_trig, &reader)) {
+ r_k_fdlimit();
r_k_fs();
r_k_misc();
r_k_miscsyscall();
diff --git a/src/user/app/tests/tests.h b/src/user/app/tests/tests.h
index 248303d..e9b06e5 100644
--- a/src/user/app/tests/tests.h
+++ b/src/user/app/tests/tests.h
@@ -7,6 +7,7 @@
void run_test(void (*fn)());
+void r_k_fdlimit(void);
void r_k_fs(void);
void r_k_misc(void);
void r_k_miscsyscall(void);