fix: correct bug and harden error handling

main
Sean McBride 4 years ago
parent 1c65516164
commit 1ae6acbbee

@ -120,6 +120,9 @@ arch_mcontext_save(struct arch_context *ctx, mcontext_t *mc)
static inline int static inline int
arch_context_switch(struct arch_context *current, struct arch_context *next) arch_context_switch(struct arch_context *current, struct arch_context *next)
{ {
/* Assumption: Software Interrupts are disabled by caller */
assert(software_interrupt_is_disabled);
/* if both current and next are NULL, there is no state change */ /* if both current and next are NULL, there is no state change */
assert(current != NULL || next != NULL); assert(current != NULL || next != NULL);

@ -2,6 +2,8 @@
#include <uv.h> #include <uv.h>
#include "panic.h"
#include "software_interrupt.h"
#include "types.h" #include "types.h"
struct module { struct module {
@ -127,24 +129,21 @@ module_initialize_memory(struct module *module)
/** /**
* Validate module, defined as having a non-NULL dynamical library handle and entry function pointer * Validate module, defined as having a non-NULL dynamical library handle and entry function pointer
* @param module - module to validate * @param module - module to validate
* @return true if valid. false if invalid
*/ */
static inline bool static inline void
module_is_valid(struct module *module) module_validate(struct module *module)
{ {
/* Assumption: Software Interrupts are disabled by caller */
assert(!software_interrupt_is_enabled());
if (!module) { if (!module) {
fprintf(stderr, "%lu | module %p | module is unexpectedly NULL\n", pthread_self(), module); panic("%lu | module %p | module is unexpectedly NULL\n", pthread_self(), module);
return false;
} else if (!module->dynamic_library_handle) { } else if (!module->dynamic_library_handle) {
fprintf(stderr, "%lu | module %p | module->dynamic_library_handle is unexpectedly NULL\n", panic("%lu | module %p | module->dynamic_library_handle is unexpectedly NULL\n", pthread_self(),
pthread_self(), module); module);
return false;
} else if (!module->main) { } else if (!module->main) {
fprintf(stderr, "%lu | module %p | module->main is unexpectedly NULL\n", pthread_self(), module); panic("%lu | module %p | module->main is unexpectedly NULL\n", pthread_self(), module);
return false;
} }
return true;
} }
/** /**

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <assert.h> #include <assert.h>
#include <panic.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
@ -31,7 +32,8 @@ software_interrupt_disable(void)
static inline void static inline void
software_interrupt_enable(void) software_interrupt_enable(void)
{ {
if (__sync_bool_compare_and_swap(&software_interrupt_is_disabled, 1, 0) == false) assert(0); if (__sync_bool_compare_and_swap(&software_interrupt_is_disabled, 1, 0) == false)
panic("Recursive call to software_interrupt_enable\n");
} }
/** /**

@ -33,6 +33,7 @@ static struct global_request_scheduler_config global_request_scheduler = { .add_
void void
global_request_scheduler_initialize(struct global_request_scheduler_config *config) global_request_scheduler_initialize(struct global_request_scheduler_config *config)
{ {
assert(config != NULL);
memcpy(&global_request_scheduler, config, sizeof(struct global_request_scheduler_config)); memcpy(&global_request_scheduler, config, sizeof(struct global_request_scheduler_config));
} }
@ -44,6 +45,7 @@ global_request_scheduler_initialize(struct global_request_scheduler_config *conf
struct sandbox_request * struct sandbox_request *
global_request_scheduler_add(struct sandbox_request *sandbox_request) global_request_scheduler_add(struct sandbox_request *sandbox_request)
{ {
assert(sandbox_request != NULL);
return global_request_scheduler.add_fn(sandbox_request); return global_request_scheduler.add_fn(sandbox_request);
} }
@ -55,6 +57,7 @@ global_request_scheduler_add(struct sandbox_request *sandbox_request)
int int
global_request_scheduler_remove(struct sandbox_request **removed_sandbox) global_request_scheduler_remove(struct sandbox_request **removed_sandbox)
{ {
assert(removed_sandbox != NULL);
return global_request_scheduler.remove_fn(removed_sandbox); return global_request_scheduler.remove_fn(removed_sandbox);
} }

@ -57,6 +57,9 @@ local_runqueue_list_get_next()
done: done:
return sandbox; return sandbox;
sandbox_allocate_err: sandbox_allocate_err:
fprintf(stderr,
"local_runqueue_list_get_next failed to allocate sandbox, returning request to global request "
"scheduler\n");
global_request_scheduler_add(sandbox_request); global_request_scheduler_add(sandbox_request);
err: err:
sandbox = NULL; sandbox = NULL;

@ -6,6 +6,7 @@
#include "local_runqueue_minheap.h" #include "local_runqueue_minheap.h"
#include "panic.h" #include "panic.h"
#include "priority_queue.h" #include "priority_queue.h"
#include "software_interrupt.h"
__thread static struct priority_queue local_runqueue_minheap; __thread static struct priority_queue local_runqueue_minheap;
@ -70,6 +71,9 @@ local_runqueue_minheap_delete(struct sandbox *sandbox)
struct sandbox * struct sandbox *
local_runqueue_minheap_get_next() local_runqueue_minheap_get_next()
{ {
/* Assumption: Software Interrupts are disabed by caller */
assert(!software_interrupt_is_enabled());
struct sandbox * sandbox = NULL; struct sandbox * sandbox = NULL;
struct sandbox_request *sandbox_request; struct sandbox_request *sandbox_request;
int sandbox_rc = local_runqueue_minheap_remove(&sandbox); int sandbox_rc = local_runqueue_minheap_remove(&sandbox);
@ -97,6 +101,8 @@ local_runqueue_minheap_get_next()
done: done:
return sandbox; return sandbox;
sandbox_allocate_err: sandbox_allocate_err:
fprintf(stderr, "local_runqueue_minheap_get_next failed to allocating sandbox. Readding request to global "
"request scheduler\n");
global_request_scheduler_add(sandbox_request); global_request_scheduler_add(sandbox_request);
err: err:
sandbox = NULL; sandbox = NULL;
@ -112,9 +118,8 @@ err:
void void
local_runqueue_minheap_preempt(ucontext_t *user_context) local_runqueue_minheap_preempt(ucontext_t *user_context)
{ {
assert(user_context != NULL); /* Assumption: Software Interrupts are disabed by caller */
assert(!software_interrupt_is_enabled());
software_interrupt_disable(); /* no nesting! */
struct sandbox *current_sandbox = current_sandbox_get(); struct sandbox *current_sandbox = current_sandbox_get();
@ -147,13 +152,11 @@ local_runqueue_minheap_preempt(ucontext_t *user_context)
/* Allocate the request */ /* Allocate the request */
struct sandbox *next_sandbox; struct sandbox *next_sandbox;
/* If sandbox allocation fails, add the request back and exit*/ /* If sandbox allocation fails, add the request back and exit*/
assert(software_interrupt_is_disabled);
if (sandbox_allocate(&next_sandbox, sandbox_request) == -1) goto err_sandbox_allocate; if (sandbox_allocate(&next_sandbox, sandbox_request) == -1) goto err_sandbox_allocate;
/* Set as runnable and add it to the runqueue */ /* Set as runnable and add it to the runqueue */
next_sandbox->state = SANDBOX_RUNNABLE; next_sandbox->state = SANDBOX_RUNNABLE;
local_runqueue_add(next_sandbox); local_runqueue_add(next_sandbox);
assert(software_interrupt_is_disabled);
/* Save the context of the currently executing sandbox before switching from it */ /* Save the context of the currently executing sandbox before switching from it */
arch_mcontext_save(&current_sandbox->ctxt, &user_context->uc_mcontext); arch_mcontext_save(&current_sandbox->ctxt, &user_context->uc_mcontext);
@ -173,7 +176,10 @@ done:
if (should_enable_software_interrupt) software_interrupt_enable(); if (should_enable_software_interrupt) software_interrupt_enable();
return; return;
err_sandbox_allocate: err_sandbox_allocate:
assert(sandbox_request != NULL); assert(sandbox_request);
fprintf(stderr,
"local_runqueue_minheap_preempt failed to allocate sandbox, returning request to global request "
"scheduler\n");
global_request_scheduler_add(sandbox_request); global_request_scheduler_add(sandbox_request);
err: err:
goto done; goto done;

@ -389,10 +389,13 @@ err_stack_allocation_failed:
int int
sandbox_allocate(struct sandbox **sandbox, struct sandbox_request *sandbox_request) sandbox_allocate(struct sandbox **sandbox, struct sandbox_request *sandbox_request)
{ {
/* Assumption: Caller has disabled software interrupts */
assert(!software_interrupt_is_enabled());
/* Validate Arguments */
assert(sandbox != NULL); assert(sandbox != NULL);
assert(sandbox_request != NULL); assert(sandbox_request != NULL);
assert(sandbox_request->module != NULL); module_validate(sandbox_request->module);
assert(module_is_valid(sandbox_request->module));
char *error_message = ""; char *error_message = "";
int rc; int rc;

@ -111,6 +111,7 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
if (current_sandbox->state == SANDBOX_RETURNED) return; if (current_sandbox->state == SANDBOX_RETURNED) return;
/* Preempt */ /* Preempt */
software_interrupt_disable();
local_runqueue_preempt(user_context); local_runqueue_preempt(user_context);
return; return;

Loading…
Cancel
Save