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
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 */
assert(current != NULL || next != NULL);

@ -2,6 +2,8 @@
#include <uv.h>
#include "panic.h"
#include "software_interrupt.h"
#include "types.h"
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
* @param module - module to validate
* @return true if valid. false if invalid
*/
static inline bool
module_is_valid(struct module *module)
static inline void
module_validate(struct module *module)
{
/* Assumption: Software Interrupts are disabled by caller */
assert(!software_interrupt_is_enabled());
if (!module) {
fprintf(stderr, "%lu | module %p | module is unexpectedly NULL\n", pthread_self(), module);
return false;
panic("%lu | module %p | module is unexpectedly NULL\n", pthread_self(), module);
} else if (!module->dynamic_library_handle) {
fprintf(stderr, "%lu | module %p | module->dynamic_library_handle is unexpectedly NULL\n",
pthread_self(), module);
return false;
panic("%lu | module %p | module->dynamic_library_handle is unexpectedly NULL\n", pthread_self(),
module);
} else if (!module->main) {
fprintf(stderr, "%lu | module %p | module->main is unexpectedly NULL\n", pthread_self(), module);
return false;
panic("%lu | module %p | module->main is unexpectedly NULL\n", pthread_self(), module);
}
return true;
}
/**

@ -1,6 +1,7 @@
#pragma once
#include <assert.h>
#include <panic.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@ -31,7 +32,8 @@ software_interrupt_disable(void)
static inline 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
global_request_scheduler_initialize(struct global_request_scheduler_config *config)
{
assert(config != NULL);
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 *
global_request_scheduler_add(struct sandbox_request *sandbox_request)
{
assert(sandbox_request != NULL);
return global_request_scheduler.add_fn(sandbox_request);
}
@ -55,6 +57,7 @@ global_request_scheduler_add(struct sandbox_request *sandbox_request)
int
global_request_scheduler_remove(struct sandbox_request **removed_sandbox)
{
assert(removed_sandbox != NULL);
return global_request_scheduler.remove_fn(removed_sandbox);
}

@ -57,6 +57,9 @@ local_runqueue_list_get_next()
done:
return sandbox;
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);
err:
sandbox = NULL;

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

@ -389,10 +389,13 @@ err_stack_allocation_failed:
int
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_request != NULL);
assert(sandbox_request->module != NULL);
assert(module_is_valid(sandbox_request->module));
module_validate(sandbox_request->module);
char *error_message = "";
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;
/* Preempt */
software_interrupt_disable();
local_runqueue_preempt(user_context);
return;

Loading…
Cancel
Save