use new errorhandling scheme
This commit is contained in:
parent
d36a38a56e
commit
e07dc59e78
5 changed files with 34 additions and 82 deletions
|
|
@ -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
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" */
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue