aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/regions.c6
-rw-r--r--src/uapi/proc.c10
-rw-r--r--tests/spawn-exhaustion/init.c35
-rw-r--r--tests/spawn-exhaustion/source.mk1
-rw-r--r--tests/spawn-exhaustion/spawn.c14
5 files changed, 63 insertions, 3 deletions
diff --git a/src/regions.c b/src/regions.c
index 2c11db0..163ec82 100644
--- a/src/regions.c
+++ b/src/regions.c
@@ -35,6 +35,9 @@ void destroy_mem_nodes()
static struct mem_region *get_mem_node()
{
struct mem_region *r = get_node(&root);
+ if (!r)
+ return NULL;
+
memset(r, 0, sizeof(struct mem_region));
return r;
}
@@ -178,6 +181,9 @@ stat_t init_region(struct mem_region_root *r, vm_t start, size_t arena_size,
start = __page(start);
arena_size = __page(arena_size);
struct mem_region *m = get_mem_node();
+ if (!m)
+ return ERR_OOMEM;
+
m->start = start;
m->end = start + arena_size;
m->flags = 0;
diff --git a/src/uapi/proc.c b/src/uapi/proc.c
index 51a1252..5eb3013 100644
--- a/src/uapi/proc.c
+++ b/src/uapi/proc.c
@@ -154,11 +154,15 @@ SYSCALL_DEFINE2(spawn)(struct tcb *t, sys_arg_t bin, sys_arg_t interp)
if (!n)
return_args1(t, ERR_OOMEM);
+ /** @todo there's currently a kind of silly thing where create_proc()
+ * creates a new thread and calls init_uvmem() on it, and now the elf
+ * loader called from prepare_proc() moves that uvmem aside, calls
+ * init_uvmem() again and finally destroys the old uvmem (assuming
+ * everything went as it was supposed to). Might have to rething these
+ * internal APIs a bit, but for now this ~works~. */
n->notify_id = c->notify_id;
if (prepare_proc(n, bin, interp)) {
- /* this kills the thread */
- orphanize(t);
- unorphanize(t);
+ destroy_proc(n);
return_args1(t, ERR_INVAL);
}
diff --git a/tests/spawn-exhaustion/init.c b/tests/spawn-exhaustion/init.c
new file mode 100644
index 0000000..1862648
--- /dev/null
+++ b/tests/spawn-exhaustion/init.c
@@ -0,0 +1,35 @@
+#include <common/test.h>
+#include <common/cpio.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(pid);
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ check(pid == 0, "illegal pid for init\n");
+ printf("finding spawn in cpio archive %lx...\n", d2);
+ struct cpio_header *cp = cpio_find_file((const void *)d2,
+ "spawn", sizeof("spawn") - 1);
+
+ check(cp, "couldn't find spawn?\n");
+ long name_len = convnum(cp->c_namesize, 8, 16);
+ uintptr_t spawn = (uintptr_t)(cp) + align_up(sizeof(struct cpio_header) + name_len, 4);
+ printf("found spawn at %lx\n", spawn);
+
+ printf("doing spawns...\n");
+
+ int counter = 0;
+ while (1) {
+ printf("spawning %d\n", counter++);
+ id_t new = sys_spawn(spawn, 0);
+ if (new < 0)
+ break;
+ }
+
+ /* could also check for memory leaks but this is good enough for now */
+ ok();
+}
diff --git a/tests/spawn-exhaustion/source.mk b/tests/spawn-exhaustion/source.mk
new file mode 100644
index 0000000..c665e49
--- /dev/null
+++ b/tests/spawn-exhaustion/source.mk
@@ -0,0 +1 @@
+DO != ./scripts/gen-simple -n spawn-exhaustion -p init -p spawn
diff --git a/tests/spawn-exhaustion/spawn.c b/tests/spawn-exhaustion/spawn.c
new file mode 100644
index 0000000..e281fc8
--- /dev/null
+++ b/tests/spawn-exhaustion/spawn.c
@@ -0,0 +1,14 @@
+#include <common/test.h>
+
+START(pid, tid, d0, d1, d2, d3)
+{
+ UNUSED(pid);
+ UNUSED(tid);
+ UNUSED(d0);
+ UNUSED(d1);
+ UNUSED(d2);
+ UNUSED(d3);
+
+ printf("shouldn't be here\n");
+ /* just die or something */
+}