X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/6ee0c41f7b32ec1dc40e41246f0b709c54ea119d..748bfdfc4d4f60631ff5d06f2f954a36f2ea8ee5:/context.c diff --git a/context.c b/context.c index 4645ebf5..8baa60e0 100644 --- a/context.c +++ b/context.c @@ -1,9 +1,9 @@ #include "imageri.h" #include -static im_slot_t slot_count; -static im_slot_destroy_t *slot_destructors; -static i_mutex_t slot_mutex; +static volatile im_slot_t slot_count = 1; +static im_slot_destroy_t *volatile slot_destructors; +static volatile i_mutex_t slot_mutex; /* =item im_context_new() @@ -38,7 +38,8 @@ im_context_new(void) { ctx->max_height = 0; ctx->max_bytes = DEF_BYTES_LIMIT; - ctx->slots = calloc(sizeof(void *), slot_count); + ctx->slot_alloc = slot_count; + ctx->slots = calloc(sizeof(void *), ctx->slot_alloc); if (!ctx->slots) { free(ctx); return NULL; @@ -104,10 +105,13 @@ im_context_refdec(im_context_t ctx, const char *where) { if (ctx->refcount != 0) return; + /* lock here to avoid slot_destructors from being moved under us */ + i_mutex_lock(slot_mutex); for (slot = 0; slot < ctx->slot_alloc; ++slot) { if (ctx->slots[slot] && slot_destructors[slot]) slot_destructors[slot](ctx->slots[slot]); } + i_mutex_unlock(slot_mutex); free(ctx->slots); @@ -128,6 +132,8 @@ im_context_refdec(im_context_t ctx, const char *where) { Clone an Imager context object, returning the result. +The error stack is not copied from the original context. + =cut */ @@ -139,36 +145,37 @@ im_context_clone(im_context_t ctx, const char *where) { if (!nctx) return NULL; - nctx->slots = calloc(sizeof(void *), slot_count); + nctx->slot_alloc = slot_count; + nctx->slots = calloc(sizeof(void *), nctx->slot_alloc); if (!nctx->slots) { free(nctx); return NULL; } - nctx->slot_alloc = slot_count; - nctx->error_sp = ctx->error_sp; + nctx->error_sp = IM_ERROR_COUNT-1; for (i = 0; i < IM_ERROR_COUNT; ++i) { - if (ctx->error_stack[i].msg) { - size_t sz = ctx->error_alloc[i]; - nctx->error_alloc[i] = sz; - nctx->error_stack[i].msg = mymalloc(sz); - memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz); - } - else { - nctx->error_alloc[i] = 0; - nctx->error_stack[i].msg = NULL; - } - nctx->error_stack[i].code = ctx->error_stack[i].code; + nctx->error_alloc[i] = 0; + nctx->error_stack[i].msg = NULL; } #ifdef IMAGER_LOG nctx->log_level = ctx->log_level; if (ctx->lg_file) { if (ctx->own_log) { int newfd = dup(fileno(ctx->lg_file)); - nctx->own_log = 1; - nctx->lg_file = fdopen(newfd, "w"); - if (nctx->lg_file) - setvbuf(nctx->lg_file, NULL, _IONBF, BUFSIZ); + if (newfd >= 0) { + nctx->own_log = 1; + nctx->lg_file = fdopen(newfd, "w"); + if (nctx->lg_file) + setvbuf(nctx->lg_file, NULL, _IONBF, BUFSIZ); + } + else { +#ifdef IMAGER_TRACE_CONTEXT + perror("im_context:failed to clone log"); +#endif + free(nctx->slots); + free(nctx); + return NULL; + } } else { /* stderr */ @@ -198,6 +205,9 @@ im_context_clone(im_context_t ctx, const char *where) { Allocate a new context-local-storage slot. +C will be called when the context is destroyed if the +corresponding slot is non-NULL. + =cut */