From fc618e08fbf77293e801be433dec976c55fa0267 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Thu, 29 Jan 2009 19:27:15 -0500 Subject: [PATCH] Thread cancellation tests in do_compress() and do_decompress(). --- src/commands.c | 197 +++++++++++++++++++++++++++++++++++++-------------------- src/lock.h | 1 + src/pwmd.c | 2 +- 3 files changed, 130 insertions(+), 70 deletions(-) diff --git a/src/commands.c b/src/commands.c index 6ec667ca..dfe17d04 100644 --- a/src/commands.c +++ b/src/commands.c @@ -50,6 +50,13 @@ #include "commands.h" #include "lock.h" +struct gz_s { + z_stream z; + gpointer out; + gboolean done; + status_msg_t which; +}; + static void *z_alloc(void *data, unsigned items, unsigned size) { return gcry_calloc(items, size); @@ -212,53 +219,84 @@ void cleanup_client(struct client_s *client) client->has_lock = has_lock; } +static void gz_cleanup(void *arg) +{ + struct gz_s **gz = (struct gz_s **)arg; + + if (!gz) + return; + + if (!(*gz)->done && (*gz)->out) + gcry_free((*gz)->out); + + + if ((*gz)->which == STATUS_COMPRESS) { + if ((*gz)->z.zalloc) + deflateEnd(&(*gz)->z); + } + else { + if ((*gz)->z.zalloc) + inflateEnd(&(*gz)->z); + } + + g_free(*gz); + *gz = NULL; +} + gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, gpointer *out, gulong *outsize, gint *rc) { - z_stream z; - gpointer pout; + struct gz_s *gz; gz_header h; gchar buf[17]; - z.zalloc = z_alloc; - z.zfree = z_free; - z.next_in = in; - z.avail_in = (uInt)insize; - z.avail_out = zlib_bufsize; - z.next_out = pout = gcry_malloc(zlib_bufsize); + gz = g_malloc0(sizeof(struct gz_s)); + + if (!gz) { + *rc = gpg_error_from_errno(ENOMEM); + return FALSE; + } - if (!pout) { + gz->which = STATUS_DECOMPRESS; + pthread_cleanup_push(gz_cleanup, &gz); + gz->z.zalloc = z_alloc; + gz->z.zfree = z_free; + gz->z.next_in = in; + gz->z.avail_in = (uInt)insize; + gz->z.avail_out = zlib_bufsize; + gz->z.next_out = gz->out = gcry_malloc(zlib_bufsize); + + if (!gz->out) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM)); *rc = Z_MEM_ERROR; + gz_cleanup(&gz); return FALSE; } - *rc = inflateInit2(&z, 47); + *rc = inflateInit2(&gz->z, 47); if (*rc != Z_OK) { - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + gz_cleanup(&gz); return FALSE; } memset(&h, 0, sizeof(gz_header)); h.comment = (guchar *)buf; h.comm_max = sizeof(buf); - *rc = inflateGetHeader(&z, &h); + *rc = inflateGetHeader(&gz->z, &h); if (*rc != Z_OK) { - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); - inflateEnd(&z); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + gz_cleanup(&gz); return FALSE; } - *rc = inflate(&z, Z_BLOCK); + *rc = inflate(&gz->z, Z_BLOCK); if (*rc != Z_OK) { - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); - inflateEnd(&z); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + gz_cleanup(&gz); return FALSE; } @@ -268,14 +306,14 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, do { gpointer p; - *rc = inflate(&z, Z_FINISH); + *rc = inflate(&gz->z, Z_FINISH); switch (*rc) { case Z_OK: break; case Z_BUF_ERROR: - if (!z.avail_out) { - p = gcry_realloc(pout, z.total_out + zlib_bufsize); + if (!gz->z.avail_out) { + p = gcry_realloc(gz->out, gz->z.total_out + zlib_bufsize); if (!p) { log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); @@ -283,11 +321,16 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, goto fail; } - pout = p; - z.next_out = pout + z.total_out; - z.avail_out = zlib_bufsize; + gz->out = p; + gz->z.next_out = gz->out + gz->z.total_out; + gz->z.avail_out = zlib_bufsize; + pthread_cleanup_push(gz_cleanup, &gz); + pthread_testcancel(); *rc = send_status(ctx, STATUS_DECOMPRESS, "%li %li", - z.total_out, insize); + gz->z.total_out, insize); + pthread_testcancel(); + pthread_cleanup_pop(0); + if (*rc) goto fail; } @@ -300,22 +343,24 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, } } while (*rc != Z_STREAM_END); - *rc = send_status(ctx, STATUS_DECOMPRESS, "%li %li", z.total_out, + pthread_testcancel(); + *rc = send_status(ctx, STATUS_DECOMPRESS, "%li %li", gz->z.total_out, insize); + pthread_testcancel(); if (*rc) goto fail; - *out = pout; - *outsize = z.total_out; - inflateEnd(&z); + *out = gz->out; + *outsize = gz->z.total_out; + gz->done = TRUE; + gz_cleanup(&gz); *rc = 0; return TRUE; fail: - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); - inflateEnd(&z); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + pthread_cleanup_pop(1); return FALSE; } @@ -736,30 +781,39 @@ done: gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, gulong size, gpointer *out, gulong *outsize, gint *rc) { - z_stream z; - gpointer pout, pin; + struct gz_s *gz; gz_header h; gchar buf[17]; gint cmd = Z_NO_FLUSH; - z.zalloc = z_alloc; - z.zfree = z_free; - z.next_in = pin = data; - z.avail_in = size < zlib_bufsize ? (uInt)size : (uInt)zlib_bufsize; - z.avail_out = (uInt)zlib_bufsize; - z.next_out = pout = gcry_malloc(zlib_bufsize); + gz = g_malloc0(sizeof(struct gz_s)); - if (!pout) { + if (!gz) { + *rc = gpg_error_from_errno(ENOMEM); + return FALSE; + } + + gz->which = STATUS_COMPRESS; + pthread_cleanup_push(gz_cleanup, &gz); + gz->z.zalloc = z_alloc; + gz->z.zfree = z_free; + gz->z.next_in = data; + gz->z.avail_in = size < zlib_bufsize ? (uInt)size : (uInt)zlib_bufsize; + gz->z.avail_out = (uInt)zlib_bufsize; + gz->z.next_out = gz->out = gcry_malloc(zlib_bufsize); + + if (!gz->out) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM)); *rc = Z_MEM_ERROR; + gz_cleanup(&gz); return FALSE; } - *rc = deflateInit2(&z, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); + *rc = deflateInit2(&gz->z, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); if (*rc != Z_OK) { - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + gz_cleanup(&gz); return FALSE; } @@ -770,26 +824,25 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, memset(&h, 0, sizeof(gz_header)); g_snprintf(buf, sizeof(buf), "%li", size); h.comment = (guchar *)buf; - *rc = deflateSetHeader(&z, &h); + *rc = deflateSetHeader(&gz->z, &h); if (*rc != Z_OK) { - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); - deflateEnd(&z); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + gz_cleanup(&gz); return FALSE; } do { gpointer p; - *rc = deflate(&z, cmd); + *rc = deflate(&gz->z, cmd); switch (*rc) { case Z_OK: break; case Z_BUF_ERROR: - if (!z.avail_out) { - p = gcry_realloc(pout, z.total_out + zlib_bufsize); + if (!gz->z.avail_out) { + p = gcry_realloc(gz->out, gz->z.total_out + zlib_bufsize); if (!p) { log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); @@ -797,25 +850,29 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, goto fail; } - pout = p; - z.next_out = pout + z.total_out; - z.avail_out = zlib_bufsize; + gz->out = p; + gz->z.next_out = gz->out + gz->z.total_out; + gz->z.avail_out = zlib_bufsize; } - if (!z.avail_in && z.total_in < size) { - if (z.total_in + zlib_bufsize > size) - z.avail_in = size - z.total_in; + if (!gz->z.avail_in && gz->z.total_in < size) { + if (gz->z.total_in + zlib_bufsize > size) + gz->z.avail_in = size - gz->z.total_in; else - z.avail_in = zlib_bufsize; + gz->z.avail_in = zlib_bufsize; + pthread_cleanup_push(gz_cleanup, &gz); + pthread_testcancel(); *rc = send_status(ctx, STATUS_COMPRESS, "%li %li", - z.total_in, size); + gz->z.total_in, size); + pthread_testcancel(); + pthread_cleanup_pop(0); if (*rc) goto fail; } - if (z.total_in >= size) + if (gz->z.total_in >= size) cmd = Z_FINISH; break; @@ -826,21 +883,23 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, } } while (*rc != Z_STREAM_END); - *rc = send_status(ctx, STATUS_COMPRESS, "%li %li", z.total_in, size); + pthread_testcancel(); + *rc = send_status(ctx, STATUS_COMPRESS, "%li %li", gz->z.total_in, size); + pthread_testcancel(); if (*rc) goto fail; - *out = pout; - *outsize = z.total_out; - deflateEnd(&z); + *out = gz->out; + *outsize = gz->z.total_out; *rc = 0; + gz->done = TRUE; + gz_cleanup(&gz); return TRUE; fail: - log_write("%s(%i): %s", __FUNCTION__, __LINE__, z.msg); - gcry_free(pout); - deflateEnd(&z); + log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); + pthread_cleanup_pop(1); return FALSE; } diff --git a/src/lock.h b/src/lock.h index fd03ae96..32d1283c 100644 --- a/src/lock.h +++ b/src/lock.h @@ -23,6 +23,7 @@ #include #include "cache.h" +#define DEBUG 1 #ifdef DEBUG #define MUTEX_LOCK_DEBUG \ log_write("%s(%i): %s: LOCK", __FILE__, __LINE__, __FUNCTION__); diff --git a/src/pwmd.c b/src/pwmd.c index 48181fe9..0e57b270 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -2589,7 +2589,7 @@ do_exit: log_write(N_("pwmd exiting normally")); #if defined(DEBUG) && !defined(MEM_DEBUG) - xdump(); + // xdump(); #endif #ifndef MEM_DEBUG xmem_deinit(); -- 2.11.4.GIT