chore: more cleanup

main
Sean McBride 5 years ago
parent 0c85cd4102
commit c4142c00f1

@ -8,7 +8,7 @@ struct module {
char name[MOD_NAME_MAX];
char path[MOD_PATH_MAX];
void * dl_handle;
void * dynamic_library_handle; // Handle to the *.so of the serverless function
mod_main_fn_t entry_fn;
mod_glb_fn_t glb_init_fn;
mod_mem_fn_t mem_init_fn;
@ -24,8 +24,10 @@ struct module {
u32 reference_count; // ref count how many instances exist here.
struct sockaddr_in srvaddr;
int srvsock, srvport;
struct sockaddr_in socket_address;
int socket_descriptor;
int port;
// unfortunately, using UV for accepting connections is not great!
// on_connection, to create a new accepted connection, will have to
// init a tcp handle, which requires a uvloop. cannot use main as
@ -51,7 +53,7 @@ struct module *module_alloc(char *mod_name, char *mod_path, i32 argument_count,
// frees only if reference_count == 0
void module_free(struct module *module);
struct module *module_find_by_name(char *name);
struct module *module_find_by_sock(int sock);
struct module *module_find_by_socket_descriptor(int sock);
static inline void
@ -73,14 +75,23 @@ module_http_info(
strcpy(module->response_content_type, response_content_type);
}
/**
* Validate module, defined as having a non-NULL dynamical library handle and entry function pointer
* @param module
* @return 1 if valid. 0 if invalid
**/
static inline int
module_is_valid(struct module *module)
{
if (module && module->dl_handle && module->entry_fn) return 1;
if (module && module->dynamic_library_handle && module->entry_fn) return 1;
return 0;
}
/**
* Invoke a module's glb_init_fn
* @param module
**/
static inline void
module_globals_init(struct module *module)
{
@ -88,6 +99,10 @@ module_globals_init(struct module *module)
module->glb_init_fn();
}
/**
* Invoke a module's tbl_init_fn
* @param module
**/
static inline void
module_table_init(struct module *module)
{
@ -95,6 +110,10 @@ module_table_init(struct module *module)
module->tbl_init_fn();
}
/**
* Invoke a module's libc_init_fn
* @param module
**/
static inline void
module_libc_init(struct module *module, i32 env, i32 args)
{
@ -102,6 +121,10 @@ module_libc_init(struct module *module, i32 env, i32 args)
module->libc_init_fn(env, args);
}
/**
* Invoke a module's mem_init_fn
* @param module
**/
static inline void
module_memory_init(struct module *module)
{
@ -109,27 +132,45 @@ module_memory_init(struct module *module)
module->mem_init_fn();
}
/**
* Invoke a module's entry function, forwarding on argc and argv
* @param module
* @param argc standard UNIX count of arguments
* @param argv standard UNIX vector of arguments
**/
static inline i32
module_entry(struct module *module, i32 argc, i32 argv)
{
return module->entry_fn(argc, argv);
}
// instantiate this module.
/**
* Increment a modules reference count
* @param module
**/
static inline void
module_acquire(struct module *module)
{
// FIXME: atomic.
// TODO: atomic.
module->reference_count++;
}
/**
* Decrement a modules reference count
* @param module
**/
static inline void
module_release(struct module *module)
{
// FIXME: atomic.
// TODO: atomic.
module->reference_count--;
}
/**
* Get a module's argument count
* @param module
* @returns the number of arguments
**/
static inline i32
module_argument_count(struct module *module)
{

@ -5,9 +5,6 @@
#include <module.h>
/* perhaps move it to module.h or sandbox.h? */
struct sandbox *util_parse_sandbox_string_custom(struct module *m, char *str, const struct sockaddr *addr);
struct sandbox *util_parse_sandbox_string_json(struct module *m, char *str, const struct sockaddr *addr);
int util_parse_modules_file_json(char *filename);
int util_parse_modules_file_custom(char *filename);
#endif /* SFRT_UTIL_H */

@ -6,9 +6,15 @@
#include <uv.h>
#include <util.h>
// In-memory representation of all active modules
static struct module *__mod_db[MOD_MAX] = { NULL };
static int __mod_free_off = 0;
/**
* Given a name, find the associated module
* @param name
* @return module or NULL if no match found
**/
struct module *
module_find_by_name(char *name)
{
@ -20,21 +26,31 @@ module_find_by_name(char *name)
return NULL;
}
/**
* Given a socket_descriptor, find the associated module
* @param socket_descriptor
* @return module or NULL if no match found
**/
struct module *
module_find_by_sock(int sock)
module_find_by_socket_descriptor(int socket_descriptor)
{
int f = __mod_free_off;
for (int i = 0; i < f; i++) {
assert(__mod_db[i]);
if (__mod_db[i]->srvsock == sock) return __mod_db[i];
if (__mod_db[i]->socket_descriptor == socket_descriptor) return __mod_db[i];
}
return NULL;
}
/**
* Adds a module to the in-memory module DB
* @param module module to add
* @return 0 on success. Aborts program on failure
**/
static inline int
module_add(struct module *module)
{
assert(module->srvsock == -1);
assert(module->socket_descriptor == -1);
int f = __sync_fetch_and_add(&__mod_free_off, 1);
assert(f < MOD_MAX);
@ -43,106 +59,153 @@ module_add(struct module *module)
return 0;
}
/**
* Start the module as a server listening at module->port
* @param module
**/
static inline void
module_server_init(struct module *module)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
assert(fd > 0);
module->srvaddr.sin_family = AF_INET;
module->srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
module->srvaddr.sin_port = htons((unsigned short)module->srvport);
// Allocate a new socket
int socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);
assert(socket_descriptor > 0);
// Configure socket address as [all addresses]:[module->port]
module->socket_address.sin_family = AF_INET;
module->socket_address.sin_addr.s_addr = htonl(INADDR_ANY);
module->socket_address.sin_port = htons((unsigned short)module->port);
// Configure the socket to allow multiple sockets to bind to the same host and port
int optval = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
optval = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (bind(fd, (struct sockaddr *)&module->srvaddr, sizeof(module->srvaddr)) < 0) {
setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
// Bind to the interface
if (bind(socket_descriptor, (struct sockaddr *)&module->socket_address, sizeof(module->socket_address)) < 0) {
perror("bind");
assert(0);
}
if (listen(fd, MOD_BACKLOG) < 0) assert(0);
module->srvsock = fd;
// Listen to the interface? Check that it is live?
if (listen(socket_descriptor, MOD_BACKLOG) < 0) assert(0);
module->socket_descriptor = socket_descriptor;
// Register the socket descriptor with our global epoll instance to monitor for incoming HTTP requests
struct epoll_event accept_evt;
accept_evt.data.ptr = (void *)module;
accept_evt.events = EPOLLIN;
if (epoll_ctl(epoll_file_descriptor, EPOLL_CTL_ADD, module->srvsock, &accept_evt) < 0) assert(0);
if (epoll_ctl(epoll_file_descriptor, EPOLL_CTL_ADD, module->socket_descriptor, &accept_evt) < 0) assert(0);
}
/**
* Module Mega Setup Function
* Creates a new module, invokes tbl_init_fn to initialize the indirect table, adds it to the module DB, and starts listening for HTTP Requests
*
* @param name
* @param path
* @param argument_count
* @param stack_size
* @param max_memory
* @param timeout
* @param port
* @param request_size
* @returns A new module or NULL in case of failure
**/
struct module *
module_alloc(char *module_name, char *module_path, i32 argument_count, u32 stack_size, u32 max_memory, u32 timeout, int port, int request_size,
module_alloc(char *name, char *path, i32 argument_count, u32 stack_size, u32 max_memory, u32 timeout, int port, int request_size,
int response_size)
{
struct module *module = (struct module *)malloc(sizeof(struct module));
if (!module) return NULL;
memset(module, 0, sizeof(struct module));
module->dl_handle = dlopen(module_path, RTLD_LAZY | RTLD_DEEPBIND);
if (module->dl_handle == NULL) goto dl_open_error;
module->entry_fn = (mod_main_fn_t)dlsym(module->dl_handle, MOD_MAIN_FN);
// Load the dynamic library *.so file with lazy function call binding and deep binding
module->dynamic_library_handle = dlopen(path, RTLD_LAZY | RTLD_DEEPBIND);
if (module->dynamic_library_handle == NULL) goto dl_open_error;
// Resolve the symbols in the dynamic library *.so file
module->entry_fn = (mod_main_fn_t)dlsym(module->dynamic_library_handle, MOD_MAIN_FN);
if (module->entry_fn == NULL) goto dl_error;
module->glb_init_fn = (mod_glb_fn_t)dlsym(module->dl_handle, MOD_GLB_FN);
module->glb_init_fn = (mod_glb_fn_t)dlsym(module->dynamic_library_handle, MOD_GLB_FN);
if (module->glb_init_fn == NULL) goto dl_error;
module->mem_init_fn = (mod_mem_fn_t)dlsym(module->dl_handle, MOD_MEM_FN);
module->mem_init_fn = (mod_mem_fn_t)dlsym(module->dynamic_library_handle, MOD_MEM_FN);
if (module->mem_init_fn == NULL) goto dl_error;
module->tbl_init_fn = (mod_tbl_fn_t)dlsym(module->dl_handle, MOD_TBL_FN);
module->tbl_init_fn = (mod_tbl_fn_t)dlsym(module->dynamic_library_handle, MOD_TBL_FN);
if (module->tbl_init_fn == NULL) goto dl_error;
module->libc_init_fn = (mod_libc_fn_t)dlsym(module->dl_handle, MOD_LIBC_FN);
module->libc_init_fn = (mod_libc_fn_t)dlsym(module->dynamic_library_handle, MOD_LIBC_FN);
if (module->libc_init_fn == NULL) goto dl_error;
strncpy(module->name, module_name, MOD_NAME_MAX);
strncpy(module->path, module_path, MOD_PATH_MAX);
// Set fields in the module struct
strncpy(module->name, name, MOD_NAME_MAX);
strncpy(module->path, path, MOD_PATH_MAX);
module->argument_count = argument_count;
module->stack_size = round_up_to_page(stack_size == 0 ? WASM_STACK_SIZE : stack_size);
module->max_memory = max_memory == 0 ? ((u64)WASM_PAGE_SIZE * WASM_MAX_PAGES) : max_memory;
module->timeout = timeout;
module->srvsock = -1;
module->srvport = port;
module->socket_descriptor = -1;
module->port = port;
if (request_size == 0) request_size = MOD_REQ_RESP_DEFAULT;
if (response_size == 0) response_size = MOD_REQ_RESP_DEFAULT;
module->max_request_size = request_size;
module->max_response_size = response_size;
module->max_request_or_response_size = round_up_to_page(request_size > response_size ? request_size : response_size);
// module_indirect_table is a thread-local struct
struct indirect_table_entry *cache_tbl = module_indirect_table;
// assumption: modules are created before enabling preemption and before running runtime-sandboxing threads..
// if this isn't a good assumption, just let the first invocation do table init..!!
// assumption: All modules are created at program start before we enable preemption or enable the execution of any worker threads
// We are checking that thread-local module_indirect_table is NULL to prove that we aren't yet preempting
// If we want to be able to do this later, we can possibly defer module_table_init until the first invocation
assert(cache_tbl == NULL);
// TODO: determine why we have to set the module_indirect_table state before calling table init and then restore the existing value
// What is the relationship between these things?
module_indirect_table = module->indirect_table;
module_table_init(module);
module_indirect_table = cache_tbl;
// Add the module to the in-memory module DB
module_add(module);
// Start listening for requests
module_server_init(module);
return module;
dl_error:
dlclose(module->dl_handle);
dlclose(module->dynamic_library_handle);
dl_open_error:
free(module);
debuglog("%s\n", dlerror());
return NULL;
}
/**
* Module Mega Teardown Function
* Closes the socket and dynamic library, and then frees the module
* @param module - the module to teardown
**/
void
module_free(struct module *module)
{
if (module == NULL) return;
if (module->dl_handle == NULL) return;
if (module->dynamic_library_handle == NULL) return;
// Do not free if we still have oustanding references
if (module->reference_count) return;
close(module->srvsock);
dlclose(module->dl_handle);
// TODO: What about the module database? Do we need to do any cleanup there?
close(module->socket_descriptor);
dlclose(module->dynamic_library_handle);
free(module);
}

@ -322,7 +322,7 @@ runtime_accept_thdfn(void *d)
socklen_t client_len = sizeof(client);
struct module * m = (struct module *)epoll_events[i].data.ptr;
assert(m);
int es = m->srvsock;
int es = m->socket_descriptor;
int s = accept(es, (struct sockaddr *)&client, &client_len);
if (s < 0) {
perror("accept");

@ -174,16 +174,16 @@ connect_n_send(void)
return -1;
}
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(SERVER_PORT);
if (inet_aton(SERVER_ADDR, &srvaddr.sin_addr) == 0) {
struct sockaddr_in socket_address;
socket_address.sin_family = AF_INET;
socket_address.sin_port = htons(SERVER_PORT);
if (inet_aton(SERVER_ADDR, &socket_address.sin_addr) == 0) {
perror("inet_addr");
close(sock);
return -1;
}
if (connect(sock, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) < 0) {
if (connect(sock, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) {
perror("connect");
close(sock);
return -1;

Loading…
Cancel
Save