diff --git a/src/backend/file.c b/src/backend/file.c index 95b4474c4..b8b8ae937 100644 --- a/src/backend/file.c +++ b/src/backend/file.c @@ -130,7 +130,7 @@ LumieraMMapings lumiera_file_mmapings (LumieraFile self) { if (!self->descriptor->mmapings) - LUMIERA_ERROR_SET (file, FILE_NOCHUNKSIZE); + LUMIERA_ERROR_SET (file, FILE_NOCHUNKSIZE, lumiera_filedescriptor_name (self->descriptor)); return self->descriptor->mmapings; } diff --git a/src/backend/filedescriptor.c b/src/backend/filedescriptor.c index 442e9b6b0..8f68e3e42 100644 --- a/src/backend/filedescriptor.c +++ b/src/backend/filedescriptor.c @@ -141,7 +141,7 @@ lumiera_filedescriptor_acquire (const char* name, int flags, LList filenode) INFO (filedescriptor, "try creating dir: %s", dir); if (mkdir (dir, 0777) == -1 && errno != EEXIST) { - LUMIERA_ERROR_SET (filedescriptor, ERRNO); + LUMIERA_ERROR_SET (filedescriptor, ERRNO, name); goto error; } *slash = '/'; @@ -152,14 +152,14 @@ lumiera_filedescriptor_acquire (const char* name, int flags, LList filenode) fd = creat (name, 0666); if (fd == -1) { - LUMIERA_ERROR_SET (filedescriptor, ERRNO); + LUMIERA_ERROR_SET (filedescriptor, ERRNO, name); goto error; } close (fd); if (stat (name, &fdesc.stat) != 0) { /* finally, no luck */ - LUMIERA_ERROR_SET (filedescriptor, ERRNO); + LUMIERA_ERROR_SET (filedescriptor, ERRNO, name); goto error; } } diff --git a/src/backend/filehandle.c b/src/backend/filehandle.c index c0d136ec2..2197a0805 100644 --- a/src/backend/filehandle.c +++ b/src/backend/filehandle.c @@ -84,7 +84,7 @@ lumiera_filehandle_handle (LumieraFilehandle self) fd = open (lumiera_filedescriptor_name (self->descriptor), lumiera_filedescriptor_flags (self->descriptor) & LUMIERA_FILE_MASK); if (fd == -1) { - LUMIERA_ERROR_SET (filehandle, ERRNO); + LUMIERA_ERROR_SET (filehandle, ERRNO, lumiera_filedescriptor_name (self->descriptor)); } else { @@ -92,13 +92,13 @@ lumiera_filehandle_handle (LumieraFilehandle self) if (fstat (fd, &st) == -1) { close (fd); - LUMIERA_ERROR_SET (filehandle, ERRNO); + LUMIERA_ERROR_SET (filehandle, ERRNO, lumiera_filedescriptor_name (self->descriptor)); } else if (!lumiera_filedescriptor_samestat (self->descriptor, &st)) { close (fd); /* Woops this is not the file we expected to use */ - LUMIERA_ERROR_SET (filehandle, FILE_CHANGED); + LUMIERA_ERROR_SET (filehandle, FILE_CHANGED, lumiera_filedescriptor_name (self->descriptor)); } } self->fd = fd; diff --git a/src/backend/filehandlecache.c b/src/backend/filehandlecache.c index 03abe08ae..23dd5fb74 100644 --- a/src/backend/filehandlecache.c +++ b/src/backend/filehandlecache.c @@ -85,7 +85,7 @@ lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFile NOTICE (filehandlecache, "overallocating filehandle"); ret = lumiera_filehandle_new (desc); if (!ret) - LUMIERA_ERROR_SET (filehandlecache, FILEHANDLECACHE_NOHANDLE); + LUMIERA_ERROR_SET (filehandlecache, FILEHANDLECACHE_NOHANDLE, lumiera_filedescriptor_name (desc)); else --self->available; } diff --git a/src/backend/mmap.c b/src/backend/mmap.c index d202a80f7..f39bafc12 100644 --- a/src/backend/mmap.c +++ b/src/backend/mmap.c @@ -140,7 +140,7 @@ lumiera_mmap_init (LumieraMMap self, LumieraFile file, off_t start, size_t size) /* extend file (writable) */ if (ftruncate (fd, begin+length) == -1) { - LUMIERA_ERROR_SET (mmap, ERRNO); + LUMIERA_ERROR_SET (mmap, ERRNO, lumiera_filedescriptor_name (file->descriptor)); goto etruncate; }; descriptor->stat.st_size = begin+length; @@ -173,7 +173,7 @@ lumiera_mmap_init (LumieraMMap self, LumieraFile file, off_t start, size_t size) break; case GIVE_UP: - LUMIERA_ERROR_SET (mmap, MMAP_SPACE); + LUMIERA_ERROR_SET (mmap, MMAP_SPACE, lumiera_filedescriptor_name (file->descriptor)); goto espace; } diff --git a/src/common/config.c b/src/common/config.c index 8801c4576..34d78dcdb 100644 --- a/src/common/config.c +++ b/src/common/config.c @@ -208,12 +208,12 @@ lumiera_config_get (const char* key, const char** value) *value = item->delim+1; } else - LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY); + LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY, key); } } else { - LUMIERA_ERROR_SET (configsys, CONFIG_SYNTAX_KEY); + LUMIERA_ERROR_SET (configsys, CONFIG_SYNTAX_KEY, key); } return *value; diff --git a/src/common/config_typed.c b/src/common/config_typed.c index 5a278665a..4fb55e6cc 100644 --- a/src/common/config_typed.c +++ b/src/common/config_typed.c @@ -77,12 +77,12 @@ lumiera_config_number_get (const char* key, long long* value) /* got it, scan it */ if (sscanf (raw_value, "%Li", value) != 1) { + LUMIERA_ERROR_SET (config_typed, CONFIG_SYNTAX_VALUE, lumiera_tmpbuf_snprintf (5000, "key '%s', value '%s'", key, raw_value)); raw_value = NULL; - LUMIERA_ERROR_SET (config_typed, CONFIG_SYNTAX_VALUE); } } else - LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY); + LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY, key); } } @@ -176,7 +176,7 @@ scan_string (const char* in) } else /* quotes doesnt match */ - LUMIERA_ERROR_SET (config_typed, CONFIG_SYNTAX_VALUE); + LUMIERA_ERROR_SET (config_typed, CONFIG_SYNTAX_VALUE, "unmatched quotes"); } else { @@ -208,7 +208,7 @@ lumiera_config_string_get (const char* key, const char** value) *value = scan_string (raw_value); } else - LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY); + LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY, key); } } @@ -253,7 +253,7 @@ lumiera_config_wordlist_get (const char* key, const char** value) *value = raw_value; } else - LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY); + LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY, key); TODO ("remove the ERROR_SET because config_get sets it already? also in all other getters in this file"); } @@ -322,7 +322,7 @@ lumiera_config_word_get (const char* key, const char** value) *value = scan_word (raw_value); } else - LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY); + LUMIERA_ERROR_SET (configsys, CONFIG_NO_ENTRY, key); } } diff --git a/src/common/configitem.c b/src/common/configitem.c index 9897158b1..82de5ae25 100644 --- a/src/common/configitem.c +++ b/src/common/configitem.c @@ -250,7 +250,7 @@ parse_directive (LumieraConfigitem self, char* itr) self->key = NULL; self->key_size = 0; - LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX); + LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX, self->line); } } else @@ -260,7 +260,7 @@ parse_directive (LumieraConfigitem self, char* itr) self->key = NULL; self->key_size = 0; - LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX); + LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX, self->line); } return self; } @@ -317,7 +317,7 @@ parse_section (LumieraConfigitem self, char* itr) self->key = NULL; self->key_size = 0; - LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX); + LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX, self->line); } } else @@ -329,7 +329,7 @@ parse_section (LumieraConfigitem self, char* itr) self->key = NULL; self->key_size = 0; - LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX); + LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX, self->line); } return self; @@ -368,7 +368,7 @@ parse_configentry (LumieraConfigitem self, char* itr) self->key = NULL; self->key_size = 0; - LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX); + LUMIERA_ERROR_SET (config_item, CONFIG_SYNTAX, self->line); } return self; diff --git a/src/common/plugin.c b/src/common/plugin.c index 3795f8511..e5045b8e9 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -283,13 +283,13 @@ lumiera_plugin_register (LumieraPlugin plugin) } break; default: - LUMIERA_ERROR_SET (plugin, PLUGIN_VERSION); + LUMIERA_ERROR_SET (plugin, PLUGIN_VERSION, plugin->name); } } } else { - LUMIERA_ERROR_SET (plugin, PLUGIN_REGISTER); + LUMIERA_ERROR_SET (plugin, PLUGIN_REGISTER, plugin->name); } } return !!lumiera_error_peek(); diff --git a/src/common/plugin_dynlib.c b/src/common/plugin_dynlib.c index afdb0e63c..920d1f385 100644 --- a/src/common/plugin_dynlib.c +++ b/src/common/plugin_dynlib.c @@ -18,6 +18,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "lib/safeclib.h" #include "common/plugin.h" #include @@ -42,18 +43,10 @@ lumiera_plugin_load_DYNLIB (const char* name) plugin = (LumieraInterface) dlsym (handle, LUMIERA_INTERFACE_DSTRING (lumieraorg__plugin, 0, lumieraorg_plugin)); if (!plugin) - LUMIERA_ERROR_SET (plugin, PLUGIN_WTF); + LUMIERA_ERROR_SET (plugin, PLUGIN_WTF, name); } else - LUMIERA_ERROR_SET (plugin, PLUGIN_OPEN); - -#ifdef DEBUG - if (lumiera_error_peek()) - { - const char* problem = dlerror(); - WARN_IF (problem, plugin, "Problem opening shared object %s : %s", name, problem); - } -#endif + LUMIERA_ERROR_SET (plugin, PLUGIN_OPEN, lumiera_tmpbuf_snprintf (4096, "%s: %s", name, dlerror())); return lumiera_plugin_init (self, handle, plugin); } diff --git a/src/gui/notification-service.cpp b/src/gui/notification-service.cpp index c09e1bbd5..f713d7390 100644 --- a/src/gui/notification-service.cpp +++ b/src/gui/notification-service.cpp @@ -147,7 +147,7 @@ namespace gui { , LUMIERA_INTERFACE_INLINE (displayInfo, "\366\075\213\163\207\040\221\233\010\366\174\374\317\126\331\205", void, (const char* text), { - if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE); + if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, text); else _instance->displayInfo(text); } @@ -155,7 +155,7 @@ namespace gui { , LUMIERA_INTERFACE_INLINE (triggerGuiShutdown, "\267\043\244\065\107\314\370\175\063\330\264\257\302\146\326\303", void, (const char* cause), { - if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE); + if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, cause); else _instance->triggerGuiShutdown(cause); } diff --git a/src/lib/error.c b/src/lib/error.c index 735f85955..caf2cf81b 100644 --- a/src/lib/error.c +++ b/src/lib/error.c @@ -33,51 +33,103 @@ predefined errors */ LUMIERA_ERROR_DEFINE (ERRNO, "errno"); +LUMIERA_ERROR_DEFINE (EERROR, "could not initialize error system"); /* Thread local storage */ static pthread_key_t lumiera_error_tls; static pthread_once_t lumiera_error_initialized = PTHREAD_ONCE_INIT; +/** + * Holding error and some context data. + */ +struct lumiera_errorcontext_struct +{ + lumiera_err err; + char* extra; +}; + +typedef struct lumiera_errorcontext_struct lumiera_errorcontext; +typedef lumiera_errorcontext* LumieraErrorcontext; + + +static void +lumiera_error_tls_delete (void* err) +{ + if (err) + free (((LumieraErrorcontext)err)->extra); +} + static void lumiera_error_tls_init (void) { - pthread_key_create (&lumiera_error_tls, NULL); + if (!!pthread_key_create (&lumiera_error_tls, lumiera_error_tls_delete)) + LUMIERA_DIE (EERROR); } -lumiera_err -lumiera_error_set (lumiera_err nerr) +LumieraErrorcontext +lumiera_error_get (void) { if (lumiera_error_initialized == PTHREAD_ONCE_INIT) pthread_once (&lumiera_error_initialized, lumiera_error_tls_init); - lumiera_err err = pthread_getspecific (lumiera_error_tls); - if (!err) - pthread_setspecific (lumiera_error_tls, nerr); + LumieraErrorcontext self = pthread_getspecific (lumiera_error_tls); + if (!self) + { + /* malloc() and not lumiera_malloc() here because nothing else might be initialized when calling this */ + self = malloc (sizeof *self); + if (!self) + LUMIERA_DIE (EERROR); - return err; + self->err = NULL; + self->extra = NULL; + pthread_setspecific (lumiera_error_tls, self); + } + + return self; +} + + +lumiera_err +lumiera_error_set (lumiera_err nerr, const char* extra) +{ + LumieraErrorcontext self = lumiera_error_get (); + + if (!self->err) + { + self->err = nerr; + free (self->extra); + if (extra) + self->extra = strdup (extra); + else + self->extra = NULL; + } + + return self->err; } lumiera_err lumiera_error (void) { - if (lumiera_error_initialized == PTHREAD_ONCE_INIT) - pthread_once (&lumiera_error_initialized, lumiera_error_tls_init); + LumieraErrorcontext self = lumiera_error_get (); + lumiera_err err = self->err; - lumiera_err err = pthread_getspecific (lumiera_error_tls); if (err) - pthread_setspecific (lumiera_error_tls, NULL); + self->err = NULL; return err; } +const char* +lumiera_error_extra (void) +{ + return lumiera_error_get ()->extra; +} + lumiera_err lumiera_error_peek (void) { - if (lumiera_error_initialized == PTHREAD_ONCE_INIT) - pthread_once (&lumiera_error_initialized, lumiera_error_tls_init); - - return pthread_getspecific (lumiera_error_tls); + return lumiera_error_get ()->err; } diff --git a/src/lib/error.h b/src/lib/error.h index 5ad8a3142..b6fb8a416 100644 --- a/src/lib/error.h +++ b/src/lib/error.h @@ -67,19 +67,30 @@ lumiera_err LUMIERA_ERROR_##err = "LUMIERA_ERROR_" #err ":" msg * @param flag NoBug flag describing the subsystem where the error was raised * @param err name of the error without the 'LUMIERA_ERROR_' prefix (example: NO_MEMORY) */ -#define LUMIERA_ERROR_SET(flag, err) \ -(({ERROR (flag, "%s", strchr(LUMIERA_ERROR_##err, ':')+1);}), \ -lumiera_error_set(LUMIERA_ERROR_##err)) +#define LUMIERA_ERROR_SET(flag, err, extra) \ + do { \ + const char* theextra = extra; \ + ERROR (flag, "%s%s%s", strchr(LUMIERA_ERROR_##err, ':')+1, theextra?": ":"", theextra?theextra:""); \ + lumiera_error_set(LUMIERA_ERROR_##err, theextra); \ + } while (0) /** * Set error state for the current thread. * If the error state of the current thread was cleared, then set it, else preserve the old state. * @param nerr name of the error with 'LUMIERA_ERROR_' prefix (example: LUMIERA_ERROR_NO_MEMORY) - * @return old state, that is NULL for success, when the state was cleared and a pointer to a pending + * @param extra a string (possibly a constructed tmpbuf) which adds some more context to the error occured this will be copied + * @return old state, that is NULL for success, when the state was cleared and a pointer to a pending * error when the error state was already set */ lumiera_err -lumiera_error_set (lumiera_err err); +lumiera_error_set (lumiera_err nerr, const char* extra); + +/** + * Query the extra context for the last error + * @return the extra string from the last error + */ +const char* +lumiera_error_extra (void); /** * Get and clear current error state. diff --git a/src/lib/exception.cpp b/src/lib/exception.cpp index 3514528bb..d59928025 100644 --- a/src/lib/exception.cpp +++ b/src/lib/exception.cpp @@ -79,7 +79,7 @@ namespace lumiera { desc_ (description), cause_ ("") { - lumiera_error_set (this->id_); + lumiera_error_set (this->id_, description.c_str ()); } @@ -91,7 +91,7 @@ namespace lumiera { desc_ (description), cause_ (extractCauseMsg(cause)) { - lumiera_error_set (this->id_); + lumiera_error_set (this->id_, description.c_str ()); } diff --git a/tests/library/test-error.c b/tests/library/test-error.c index 0133c2b4c..0a2d418a4 100644 --- a/tests/library/test-error.c +++ b/tests/library/test-error.c @@ -35,7 +35,7 @@ main (int argc, char** argv) if (!strcmp(argv[1], "set")) { - lumiera_error_set (LUMIERA_ERROR_TEST); + lumiera_error_set (LUMIERA_ERROR_TEST, NULL); } if (!strcmp(argv[1], "get_no")) @@ -47,7 +47,7 @@ main (int argc, char** argv) if (!strcmp(argv[1], "get")) { - lumiera_error_set (LUMIERA_ERROR_TEST); + lumiera_error_set (LUMIERA_ERROR_TEST, NULL); const char* err; err = lumiera_error (); printf ("%s\n", err); @@ -55,7 +55,7 @@ main (int argc, char** argv) if (!strcmp(argv[1], "get2")) { - lumiera_error_set (LUMIERA_ERROR_TEST); + lumiera_error_set (LUMIERA_ERROR_TEST, NULL); const char* err; err = lumiera_error (); printf ("%s\n", err);