use new errorhandling scheme

This commit is contained in:
Christian Thaeter 2007-08-14 04:56:55 +02:00
parent d36a38a56e
commit e07dc59e78
5 changed files with 34 additions and 82 deletions

View file

@ -29,6 +29,8 @@ AC_COPYRIGHT([
AC_PROG_CC AC_PROG_CC
AC_PROG_CPP AC_PROG_CPP
AC_PROG_CXX AC_PROG_CXX
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
# #

View file

@ -28,26 +28,18 @@
#include "plugin.h" #include "plugin.h"
/*
TODO cinelerra_xmalloc which aborts on allocation error
or cinelerra_die() function
TODO move CINELERRA_DIE elsewhere (cinlib.h?)
*/
#define CINELERRA_DIE do{NOBUG_LOG(NOBUG_ON, LOG_EMERG, "aborting due fatal error"); abort();}while(0)
/* TODO should be set by the build system to the actual plugin path */ /* TODO should be set by the build system to the actual plugin path */
#define CINELERRA_PLUGIN_PATH "~/.cinelerra3/plugins:/usr/local/lib/cinelerra3/plugins" #define CINELERRA_PLUGIN_PATH "~/.cinelerra3/plugins:/usr/local/lib/cinelerra3/plugins"
#define CINELERRA_PLUGIN_PREFIX "lib"
NOBUG_DEFINE_FLAG (cinelerra_plugin); NOBUG_DEFINE_FLAG (cinelerra_plugin);
/* errors */ /* errors */
const char* CINELERRA_PLUGIN_SUCCESS = NULL; CINELERRA_ERROR_DEFINE(PLUGIN_DLOPEN, "Could not open plugin");
const char* CINELERRA_PLUGIN_EDLOPEN = "Could not open plugin"; CINELERRA_ERROR_DEFINE(PLUGIN_HOOK, "Hook function failed");
const char* CINELERRA_PLUGIN_EHOOK = "Hook function failed"; CINELERRA_ERROR_DEFINE(PLUGIN_NFILE, "No such plugin");
const char* CINELERRA_PLUGIN_ENFOUND = "No such plugin"; CINELERRA_ERROR_DEFINE(PLUGIN_NIFACE, "No such interface");
const char* CINELERRA_PLUGIN_ENIFACE = "No such interface"; CINELERRA_ERROR_DEFINE(PLUGIN_REVISION, "Interface revision too old");
const char* CINELERRA_PLUGIN_EREVISION = "Interface revision too old";
/* /*
supported (planned) plugin types and their file extensions supported (planned) plugin types and their file extensions
@ -68,6 +60,7 @@ static const struct
{ {
{"plugin", CINELERRA_PLUGIN_DYNLIB}, {"plugin", CINELERRA_PLUGIN_DYNLIB},
{"so", CINELERRA_PLUGIN_DYNLIB}, {"so", CINELERRA_PLUGIN_DYNLIB},
{"o", CINELERRA_PLUGIN_DYNLIB},
{"tcc", CINELERRA_PLUGIN_CSOURCE}, {"tcc", CINELERRA_PLUGIN_CSOURCE},
{"c", CINELERRA_PLUGIN_CSOURCE}, {"c", CINELERRA_PLUGIN_CSOURCE},
/* extend here */ /* extend here */
@ -103,16 +96,6 @@ void* cinelerra_plugin_registry = NULL;
/* plugin operations are protected by one big mutex */ /* plugin operations are protected by one big mutex */
pthread_mutex_t cinelerra_plugin_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t cinelerra_plugin_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Thread local storage, for now only the error state */
static pthread_key_t cinelerra_plugin_tls_error;
static pthread_once_t cinelerra_plugin_initialized = PTHREAD_ONCE_INIT;
void
cinelerra_plugin_tls_init (void)
{
pthread_key_create (&cinelerra_plugin_tls_error, NULL);
}
/* the compare function for the registry tree */ /* the compare function for the registry tree */
static int static int
cinelerra_plugin_name_cmp (const void* a, const void* b) cinelerra_plugin_name_cmp (const void* a, const void* b)
@ -121,22 +104,6 @@ cinelerra_plugin_name_cmp (const void* a, const void* b)
} }
const char*
cinelerra_plugin_error ()
{
pthread_once (&cinelerra_plugin_initialized, cinelerra_plugin_tls_init);
const char* err = pthread_getspecific (cinelerra_plugin_tls_error);
pthread_setspecific (cinelerra_plugin_tls_error, CINELERRA_PLUGIN_SUCCESS);
return err;
}
static void
cinelerra_plugin_error_set (const char* err)
{
pthread_setspecific (cinelerra_plugin_tls_error, err);
}
int int
cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path) cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path)
{ {
@ -160,7 +127,7 @@ cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path)
for (int i = 0; cinelerra_plugin_extensions[i].ext; ++i) for (int i = 0; cinelerra_plugin_extensions[i].ext; ++i)
{ {
/* path/name.extension */ /* path/name.extension */
int r = snprintf(pathname, 1024, "%s/%s.%s", tok, self->name, cinelerra_plugin_extensions[i].ext); int r = snprintf(pathname, 1024, CINELERRA_PLUGIN_PREFIX "%s/%s.%s", tok, self->name, cinelerra_plugin_extensions[i].ext);
if (r >= 1024) if (r >= 1024)
return -1; /*TODO error handling, name too long*/ return -1; /*TODO error handling, name too long*/
@ -170,7 +137,7 @@ cinelerra_plugin_lookup (struct cinelerra_plugin* self, const char* path)
{ {
/* got it */ /* got it */
self->pathname = strdup (pathname); self->pathname = strdup (pathname);
if (!self->pathname) CINELERRA_DIE; if (!self->pathname) CINELERRA_DIE("out of memory");
self->type = cinelerra_plugin_extensions[i].type; self->type = cinelerra_plugin_extensions[i].type;
return 0; return 0;
} }
@ -185,8 +152,6 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
//REQUIRE (min_revision > sizeof(struct cinelerra_interface), "try to use an empty interface eh?"); //REQUIRE (min_revision > sizeof(struct cinelerra_interface), "try to use an empty interface eh?");
REQUIRE (interface, "interface name must be given"); REQUIRE (interface, "interface name must be given");
pthread_once (&cinelerra_plugin_initialized, cinelerra_plugin_tls_init);
pthread_mutex_lock (&cinelerra_plugin_mutex); pthread_mutex_lock (&cinelerra_plugin_mutex);
struct cinelerra_plugin plugin; struct cinelerra_plugin plugin;
@ -195,7 +160,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
plugin.name = name; /* for searching */ plugin.name = name; /* for searching */
found = tsearch (&plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp); found = tsearch (&plugin, &cinelerra_plugin_registry, cinelerra_plugin_name_cmp);
if (!found) CINELERRA_DIE; if (!found) CINELERRA_DIE("out of memory");
if (*found == &plugin) if (*found == &plugin)
{ {
@ -203,13 +168,13 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
/* now really create new item */ /* now really create new item */
*found = malloc (sizeof (struct cinelerra_plugin)); *found = malloc (sizeof (struct cinelerra_plugin));
if (!*found) CINELERRA_DIE; if (!*found) CINELERRA_DIE("out of memory");
if (name) /* NULL is main app, no lookup needed */ if (name) /* NULL is main app, no lookup needed */
{ {
/*lookup for $CINELERRA_PLUGIN_PATH*/ /*lookup for $CINELERRA_PLUGIN_PATH*/
(*found)->name = strdup (name); (*found)->name = strdup (name);
if (!(*found)->name) CINELERRA_DIE; if (!(*found)->name) CINELERRA_DIE("out of memory");
if (!cinelerra_plugin_lookup (*found, getenv("CINELERRA_PLUGIN_PATH")) if (!cinelerra_plugin_lookup (*found, getenv("CINELERRA_PLUGIN_PATH"))
#ifdef CINELERRA_PLUGIN_PATH #ifdef CINELERRA_PLUGIN_PATH
@ -218,7 +183,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
#endif #endif
) )
{ {
cinelerra_plugin_error_set (CINELERRA_PLUGIN_ENFOUND); cinelerra_error_set (CINELERRA_ERROR_PLUGIN_NFILE);
goto elookup; goto elookup;
} }
} }
@ -237,7 +202,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
if (!(*found)->handle) if (!(*found)->handle)
{ {
ERROR (cinelerra_plugin, "dlopen failed: %s", dlerror()); ERROR (cinelerra_plugin, "dlopen failed: %s", dlerror());
cinelerra_plugin_error_set (CINELERRA_PLUGIN_EDLOPEN); cinelerra_error_set (CINELERRA_ERROR_PLUGIN_DLOPEN);
goto edlopen; goto edlopen;
} }
@ -246,7 +211,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
if (init && init()) if (init && init())
{ {
ERROR (cinelerra_plugin, "cinelerra_plugin_init failed: %s: %s", name, interface); ERROR (cinelerra_plugin, "cinelerra_plugin_init failed: %s: %s", name, interface);
cinelerra_plugin_error_set (CINELERRA_PLUGIN_EHOOK); cinelerra_error_set (CINELERRA_ERROR_PLUGIN_HOOK);
goto einit; goto einit;
} }
} }
@ -258,7 +223,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
if (!ret) if (!ret)
{ {
ERROR (cinelerra_plugin, "plugin %s doesnt provide interface %s", name, interface); ERROR (cinelerra_plugin, "plugin %s doesnt provide interface %s", name, interface);
cinelerra_plugin_error_set (CINELERRA_PLUGIN_ENIFACE); cinelerra_error_set (CINELERRA_ERROR_PLUGIN_NIFACE);
goto edlsym; goto edlsym;
} }
@ -266,7 +231,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
if (ret->size < min_revision) if (ret->size < min_revision)
{ {
ERROR (cinelerra_plugin, "plugin %s provides older interface %s revision than required", name, interface); ERROR (cinelerra_plugin, "plugin %s provides older interface %s revision than required", name, interface);
cinelerra_plugin_error_set (CINELERRA_PLUGIN_EREVISION); cinelerra_error_set (CINELERRA_ERROR_PLUGIN_REVISION);
goto erevision; goto erevision;
} }
@ -276,7 +241,7 @@ cinelerra_interface_open (const char* name, const char* interface, size_t min_re
if (ret->open && ret->open()) if (ret->open && ret->open())
{ {
ERROR (cinelerra_plugin, "open hook indicated an error"); ERROR (cinelerra_plugin, "open hook indicated an error");
cinelerra_plugin_error_set (CINELERRA_PLUGIN_EHOOK); cinelerra_error_set (CINELERRA_ERROR_PLUGIN_HOOK);
goto eopen; goto eopen;
} }

View file

@ -30,6 +30,8 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
#include <nobug.h> #include <nobug.h>
#include "error.h"
NOBUG_DECLARE_FLAG (cinelerra_plugin); NOBUG_DECLARE_FLAG (cinelerra_plugin);
/* tool macros*/ /* tool macros*/
@ -129,30 +131,11 @@ cinelerra_plugin_unload (const char* plugin);
void void
cinelerra_plugin_expire (time_t age); cinelerra_plugin_expire (time_t age);
/** CINELERRA_ERROR_DECLARE(PLUGIN_DLOPEN);
* Query and reset the error state. CINELERRA_ERROR_DECLARE(PLUGIN_HOOK);
* report last error, reset error state. Errors are thread local. CINELERRA_ERROR_DECLARE(PLUGIN_NFILE);
* Error strings are guaranteed to point to a C string with a unique comparable address. CINELERRA_ERROR_DECLARE(PLUGIN_NIFACE);
* Note that the error state gets cleared by calling this function. The application may store it temporary for further handling. CINELERRA_ERROR_DECLARE(PLUGIN_REVISION);
* @return pointer to one of the error C-strings, NULL when no error happened.
*/
const char*
cinelerra_plugin_error ();
/// success, NULL
extern const char* CINELERRA_PLUGIN_SUCCESS;
/// memory allocation error
extern const char* CINELERRA_PLUGIN_EALLOC;
/// dlopen failed
extern const char* CINELERRA_PLUGIN_EDLOPEN;
/// dlopen failed
extern const char* CINELERRA_PLUGIN_EHOOK;
/// Plugin not found
extern const char* CINELERRA_PLUGIN_ENFOUND;
/// no such interface
extern const char* CINELERRA_PLUGIN_ENIFACE;
/// revision not sufficient
extern const char* CINELERRA_PLUGIN_EREVISION;
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -18,13 +18,14 @@
examples_srcdir = $(top_srcdir)/tests/examples examples_srcdir = $(top_srcdir)/tests/examples
noinst_PROGRAMS += plugin_example noinst_PROGRAMS += plugin_example
plugin_example_CFLAGS = $(CFLAGS) -std=gnu99 -Wall -Werror plugin_example_CFLAGS = $(AM_CFLAGS) -std=gnu99 -Wall -Werror
plugin_example_CPPFLAGS = $(CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/ plugin_example_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/
plugin_example_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl plugin_example_LDADD = $(builddir)/libcin3.a -lnobugmt -lpthread -ldl
plugin_example_SOURCES = $(examples_srcdir)/plugin_main.c plugin_example_SOURCES = $(examples_srcdir)/plugin_main.c
noinst_HEADERS += $(examples_srcdir)/hello_interface.h noinst_HEADERS += $(examples_srcdir)/hello_interface.h
#noinst_LTLIBRARIES += example_plugin.la check_LTLIBRARIES = example_plugin.la
#example_plugin_la_CPPFLAGS = $(CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/ example_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -std=gnu99 -Wall -Werror -I$(top_srcdir)/src/lib/
#example_plugin_la_SOURCES = $(examples_srcdir)/example_plugin.c example_plugin_la_SOURCES = $(examples_srcdir)/example_plugin.c
example_plugin_la_LDFLAGS = -module

View file

@ -7,6 +7,7 @@
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
NOBUG_INIT;
/* /*
we have a plugin 'hello_1' which provides us 2 hello interfaces, one for english and one for german output, we have a plugin 'hello_1' which provides us 2 hello interfaces, one for english and one for german output,
open both try them, close them. open both try them, close them.