diff options
| author | 2025-11-28 20:03:39 -0600 | |
|---|---|---|
| committer | 2025-11-28 20:03:39 -0600 | |
| commit | b36c1ce0ebc9fc08efcc85566f26a147e1cdfad1 (patch) | |
| tree | 039eab4e9e874712718676dd3435e9ca88ae5665 /src/plugins.c | |
| parent | more work on plugins (diff) | |
[incomplete] random changes before resetorig
Diffstat (limited to 'src/plugins.c')
| -rw-r--r-- | src/plugins.c | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/src/plugins.c b/src/plugins.c index b96aade..8ccde06 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -30,10 +30,22 @@ struct ptx__plugin_handle_tag ptx_plugin_t *next; int path_fd; + int pl_state; /* used to assert that the application is following its contract with plugins */ + /* plugin filename */ char fname[1]; }; +enum { + PL_STATE_NEW, /* plugin struct just initialized */ + PL_STATE_LOADED, /* plugin module loaded */ + PL_STATE_INITIALIZING, /* plugin initializer call started */ + PL_STATE_INITIALIZED, /* plugin initializer completed */ + PL_STATE_DEINITIALIZED, /* plugin deinitializer called */ + PL_STATE_ERROR, /* error in initializer, only valid operation is free */ + PL_STATE_UNLOADED /* plugin unloaded */ +}; + ptx_plugin_manager_t *ptx_plugin_manager_new(void) { ptx_plugin_manager_t *mgr = malloc(sizeof(ptx_plugin_manager_t)); @@ -46,7 +58,7 @@ ptx_plugin_manager_t *ptx_plugin_manager_new(void) } /* inform the plugin that it is about to be unloaded. It should clean up its resources. */ -static void deinit_plugin(ptx_plugin_t *plugin); +static int deinit_plugin(ptx_plugin_t *plugin, void **presume); /* unload/cleanup/free the plugin. */ static void free_plugin(ptx_plugin_t *plugin); @@ -58,7 +70,7 @@ void ptx_plugin_manager_free(ptx_plugin_manager_t *mgr) /* do cleanup */ for (ptx_plugin_t *plugin = mgr->pl_head, *next; plugin; plugin = next) { next = plugin->next; - deinit_plugin(plugin); + deinit_plugin(plugin, NULL); /* result ignored (not resuming) */ free_plugin(plugin); } @@ -82,6 +94,7 @@ static ptx_plugin_t *load_plugin(ptx_plugin_manager_t *manager, const char *plug goto cleanup; } + plugin->pl_state = PL_STATE_NEW; plugin->manager = manager; memcpy(plugin->fname, plugin_fname, fnamelen); /* NUL-termination achieved thanks to calloc */ @@ -99,8 +112,19 @@ static ptx_plugin_t *load_plugin(ptx_plugin_manager_t *manager, const char *plug goto cleanup; } + if (pl_desc->desc_len != sizeof(struct ptx_plugin_desc)) { + fprintf(stderr, "(plugin) %s: descriptor struct size mismatch: %zu != %zu (expected)\n", plugin_fname, pl_desc->desc_len, sizeof(struct ptx_plugin_desc)); + goto cleanup; + } + + if (pl_desc->desc_ver != PTX_CUR_PLUGIN_VERSION) { + fprintf(stderr, "(plugin) %s: is for a different version of ptxmc! %u != %u (expected)\n", plugin_fname, pl_desc->desc_ver, PTX_CUR_PLUGIN_VERSION); + goto cleanup; + } + plugin->desc = pl_desc; + plugin->pl_state = PL_STATE_LOADED; return plugin; cleanup: @@ -182,15 +206,72 @@ cleanup_iter: return 0; } -static void deinit_plugin(ptx_plugin_t *plugin) +static int init_plugin(ptx_plugin_t *plugin, void *resume) { - /* TODO */ - UNUSED(plugin); + assert(plugin); + assert(plugin->pl_state == plugin->pl_state == PL_STATE_LOADED); + + plugin->pl_state = PL_STATE_INITIALIZING; + int result = 0; + + if (plugin->desc->init_proc) { + result = (plugin->desc->init_proc)(plugin, resume); + } else { + fprintf(stderr, "(plugin) warning: plugin %s/%s has no initialization function! (does it do anything?)\n", plugin->desc->name, plugin->fname); + } + + if (result < 0) { + plugin->pl_state = PL_STATE_ERROR; + fprintf(stderr, "(plugin) init_plugin: %s/%s: initializer failed (%d)\n", plugin->desc->name, plugin->fname, result); + } else { + plugin->pl_state = PL_STATE_INITIALIZED; + } + + return result; +} + +int ptx_plugin_manager_init_plugins(ptx_plugin_manager_t *mgr) +{ + for (ptx_plugin_t *plugin = mgr->pl_head; plugin; plugin = plugin->next) + { + if (plugin->pl_state >= PL_STATE_INITIALIZED) continue; + assert(plugin->pl_state != PL_STATE_INITIALIZING); /* function should never be called from a plugin initializer */ + + init_plugin(plugin, NULL); + } +} + +static int deinit_plugin(ptx_plugin_t *plugin, void **presume) +{ + assert(plugin); + assert(plugin->pl_state >= PL_STATE_INITIALIZED && plugin->pl_state < PL_STATE_DEINITIALIZED); + + int result = DEINIT_OK; + if (plugin->desc->deinit_proc) { + result = (plugin->desc->deinit_proc)(plugin, presume); + } else { + result = presume ? DEINIT_ERR_RESUME_UNSUPPORTED : DEINIT_OK; + } + + plugin->pl_state = PL_STATE_DEINITIALIZED; + return result; } static void free_plugin(ptx_plugin_t *plugin) { + assert(plugin->pl_state < PL_STATE_INITIALIZED || plugin->pl_state >= PL_STATE_DEINITIALIZED); + dlclose(plugin->modp); close(plugin->path_fd); + + plugin->pl_state = PL_STATE_UNLOADED; /* state never observed by the software */ + free(plugin); } + +PTX_API void ptx_plugin_set_mainloop_func(ptx_plugin_t *plugin, void *func) +{ + assert(plugin); + assert(plugin->pl_state == PL_STATE_INITIALIZING || plugin->pl_state == PL_STATE_INITIALIZED); + UNUSED(plugin, func); +} |
