From 5cb203140420db2bb4f317186b9a48faf190efb3 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Wed, 28 Jan 2009 21:20:05 -0500 Subject: [PATCH] More thread cancelation tests and handlers. --- src/commands.c | 199 ++++++++++++++++++++++++++++++++++++++++----------------- src/pwmd.c | 9 ++- 2 files changed, 150 insertions(+), 58 deletions(-) diff --git a/src/commands.c b/src/commands.c index d627fe87..24e46311 100644 --- a/src/commands.c +++ b/src/commands.c @@ -78,6 +78,7 @@ static gpg_error_t file_modified(struct client_s *client) return EPWMD_FILE_MODIFIED; } + pthread_testcancel(); return 0; } @@ -173,6 +174,9 @@ void free_client(struct client_s *client) if (client->crypto) cleanup_crypto(&client->crypto); + + if (client->xml_error) + xmlResetError(client->xml_error); } void cleanup_client(struct client_s *client) @@ -490,8 +494,11 @@ static gboolean validate_access(struct client_s *cl, const gchar *filename) } #endif -static void open_command_cleanup_handler(void *arg) +static void req_cleanup(void *arg) { + if (!arg) + return; + g_strfreev((gchar **)arg); } @@ -506,7 +513,7 @@ static int open_command(assuan_context_t ctx, char *line) if ((req = split_input_line(line, " ", 2)) != NULL) filename = req[0]; - pthread_cleanup_push(open_command_cleanup_handler, req); + pthread_cleanup_push(req_cleanup, req); if (!filename || !*filename) { g_strfreev(req); @@ -1451,7 +1458,9 @@ static int store_command(assuan_context_t ctx, char *line) if (rc) return send_error(ctx, rc); + pthread_testcancel(); rc = assuan_inquire_ext(ctx, "STORE", 0, store_command_finalize, ctx); + pthread_testcancel(); if (rc) return send_error(ctx, rc); @@ -1503,7 +1512,9 @@ static int get_command(assuan_context_t ctx, char *line) if (!n || !n->content || !*n->content) return send_error(ctx, EPWMD_EMPTY_ELEMENT); + pthread_testcancel(); rc = assuan_send_data(ctx, n->content, xmlStrlen(n->content)); + pthread_testcancel(); return send_error(ctx, rc); } @@ -1556,6 +1567,7 @@ static xmlNodePtr realpath_elements_cb(xmlNodePtr node, gchar **target, return node; } +static void list_command_cleanup1(void *arg); static int realpath_command(assuan_context_t ctx, char *line) { gpg_error_t rc; @@ -1624,11 +1636,41 @@ again: } } + pthread_cleanup_push(list_command_cleanup1, string); + pthread_testcancel(); rc = assuan_send_data(ctx, string->str, string->len); - g_string_free(string, TRUE); + pthread_testcancel(); + pthread_cleanup_pop(1); return send_error(ctx, rc); } +static void list_command_cleanup1(void *arg) +{ + g_string_free((GString *)arg, TRUE); +} + +static void list_command_cleanup2(void *arg) +{ + struct element_list_s *elements = arg; + + if (elements) { + gint total = g_slist_length(elements->list); + gint i; + + for (i = 0; i < total; i++) { + gchar *tmp = g_slist_nth_data(elements->list, i); + g_free(tmp); + } + + g_slist_free(elements->list); + + if (elements->prefix) + g_free(elements->prefix); + + g_free(elements); + } +} + static int list_command(assuan_context_t ctx, char *line) { struct client_s *client = assuan_get_pointer(ctx); @@ -1648,12 +1690,15 @@ static int list_command(assuan_context_t ctx, char *line) GString *str; rc = list_accounts(client->doc, &str); + pthread_cleanup_push(list_command_cleanup1, str); if (rc) return send_error(ctx, rc); + pthread_testcancel(); rc = assuan_send_data(ctx, str->str, str->len); - g_string_free(str, TRUE); + pthread_testcancel(); + pthread_cleanup_pop(1); return send_error(ctx, rc); } @@ -1665,7 +1710,10 @@ static int list_command(assuan_context_t ctx, char *line) goto fail; } + pthread_cleanup_push(list_command_cleanup2, elements); + pthread_testcancel(); rc = create_path_list(client->doc, elements, line); + pthread_testcancel(); if (rc) goto fail; @@ -1688,35 +1736,24 @@ static int list_command(assuan_context_t ctx, char *line) goto fail; } + pthread_cleanup_push(list_command_cleanup1, str); + for (i = 0; i < total; i++) { tmp = g_slist_nth_data(elements->list, i); g_string_append_printf(str, "%s%s", tmp, i+1 == total ? "" : "\n"); } + pthread_testcancel(); rc = assuan_send_data(ctx, str->str, str->len); - g_string_free(str, TRUE); + pthread_testcancel(); + pthread_cleanup_pop(1); } else rc = EPWMD_EMPTY_ELEMENT; fail: - if (elements) { - gint total = g_slist_length(elements->list); - gint i; - - for (i = 0; i < total; i++) { - tmp = g_slist_nth_data(elements->list, i); - g_free(tmp); - } - - g_slist_free(elements->list); - - if (elements->prefix) - g_free(elements->prefix); - - g_free(elements); - } - + if (1) {} + pthread_cleanup_pop(1); return send_error(ctx, rc); } @@ -1816,9 +1853,13 @@ static int attribute_list(assuan_context_t ctx, gchar **req) return gpg_error_from_errno(ENOMEM); } + pthread_cleanup_push(g_free, line); + pthread_cleanup_push(req_cleanup, attrlist); + pthread_testcancel(); rc = assuan_send_data(ctx, line, strlen(line)); - g_free(line); - g_strfreev(attrlist); + pthread_testcancel(); + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); return rc; } @@ -2137,8 +2178,11 @@ static int attribute_get(assuan_context_t ctx, gchar **req) if ((a = xmlGetProp(n, (xmlChar *)req[0])) == NULL) return EPWMD_ATTR_NOT_FOUND; + pthread_cleanup_push(xmlFree, a); + pthread_testcancel(); rc = assuan_send_data(ctx, a, xmlStrlen(a)); - xmlFree(a); + pthread_testcancel(); + pthread_cleanup_pop(1); return rc; fail: @@ -2227,6 +2271,8 @@ static int attr_command(assuan_context_t ctx, char *line) return send_error(ctx, EPWMD_COMMAND_SYNTAX); } + pthread_cleanup_push(req_cleanup, req); + if (g_ascii_strcasecmp(req[0], "SET") == 0) rc = attribute_set(client, req+1); else if (g_ascii_strcasecmp(req[0], "GET") == 0) @@ -2238,7 +2284,7 @@ static int attr_command(assuan_context_t ctx, char *line) else rc = EPWMD_COMMAND_SYNTAX; - g_strfreev(req); + pthread_cleanup_pop(1); return send_error(ctx, rc); } @@ -2254,6 +2300,7 @@ static int iscached_command(assuan_context_t ctx, char *line) gcry_md_hash_buffer(GCRY_MD_MD5, md5file, req[0], strlen(req[0])); g_strfreev(req); + pthread_cleanup_push(pthread_mutex_unlock, (void *)&cache_mutex); CACHE_LOCK(ctx); if (cache_iscached(md5file) == FALSE) { @@ -2262,6 +2309,7 @@ static int iscached_command(assuan_context_t ctx, char *line) } CACHE_UNLOCK; + pthread_cleanup_pop(0); return send_error(ctx, 0); } @@ -2271,6 +2319,7 @@ static int clearcache_command(assuan_context_t ctx, char *line) gchar **req = split_input_line(line, " ", 0); guchar md5file[16]; + pthread_cleanup_push(pthread_mutex_unlock, (void *)&cache_mutex); CACHE_LOCK(ctx); if (!req || !*req) { @@ -2289,6 +2338,7 @@ static int clearcache_command(assuan_context_t ctx, char *line) } CACHE_UNLOCK; + pthread_cleanup_pop(0); return send_error(ctx, 0); } @@ -2300,6 +2350,8 @@ static int cachetimeout_command(assuan_context_t ctx, char *line) gchar *p; struct client_s *client = assuan_get_pointer(ctx); + pthread_cleanup_push(req_cleanup, req); + if (!req || !*req || !req[1]) { g_strfreev(req); return send_error(ctx, EPWMD_COMMAND_SYNTAX); @@ -2314,7 +2366,8 @@ static int cachetimeout_command(assuan_context_t ctx, char *line) } gcry_md_hash_buffer(GCRY_MD_MD5, md5file, req[1], strlen(req[1])); - g_strfreev(req); + pthread_cleanup_pop(1); + pthread_cleanup_push(pthread_mutex_unlock, (void *)&cache_mutex); CACHE_LOCK(client->ctx); if (cache_set_timeout(md5file, timeout) == FALSE) { @@ -2323,6 +2376,7 @@ static int cachetimeout_command(assuan_context_t ctx, char *line) } CACHE_UNLOCK; + pthread_cleanup_pop(0); return send_error(ctx, 0); } @@ -2348,8 +2402,11 @@ static int dump_command(assuan_context_t ctx, char *line) return send_syserror(ctx, ENOMEM); } + pthread_cleanup_push(xmlFree, xml); + pthread_testcancel(); rc = assuan_send_data(ctx, xml, len); - xmlFree(xml); + pthread_testcancel(); + pthread_cleanup_pop(1); return send_error(ctx, rc); } @@ -2391,19 +2448,42 @@ static int getconfig_command(assuan_context_t ctx, gchar *line) } p = tmp; + pthread_cleanup_push(g_free, p); + pthread_testcancel(); rc = assuan_send_data(ctx, p, strlen(p)); - g_free(p); + pthread_testcancel(); + pthread_cleanup_pop(1); return send_error(ctx, rc); } +struct xpath_s { + xmlXPathContextPtr xp; + xmlXPathObjectPtr result; + xmlBufferPtr buf; + gchar **req; +}; + +static void xpath_command_cleanup(void *arg) +{ + struct xpath_s *xpath = arg; + + req_cleanup(xpath->req); + + if (xpath->buf) + xmlBufferFree(xpath->buf); + + if (xpath->result) + xmlXPathFreeObject(xpath->result); + + if (xpath->xp) + xmlXPathFreeContext(xpath->xp); +} + static int xpath_command(assuan_context_t ctx, gchar *line) { struct client_s *client = assuan_get_pointer(ctx); gpg_error_t rc; - xmlXPathContextPtr xp; - xmlXPathObjectPtr result; - xmlBufferPtr buf = NULL; - gchar **req = NULL; + struct xpath_s xpath; if (disable_list_and_dump == TRUE) return send_error(ctx, GPG_ERR_NOT_IMPLEMENTED); @@ -2416,54 +2496,53 @@ static int xpath_command(assuan_context_t ctx, gchar *line) if (!line || !*line) return send_error(ctx, EPWMD_COMMAND_SYNTAX); - if ((req = split_input_line(line, "\t", 2)) == NULL) { - if (strv_printf(&req, "%s", line) == FALSE) + memset(&xpath, 0, sizeof(struct xpath_s)); + pthread_cleanup_push(xpath_command_cleanup, &xpath); + + if ((xpath.req = split_input_line(line, "\t", 2)) == NULL) { + if (strv_printf(&xpath.req, "%s", line) == FALSE) return send_syserror(ctx, ENOMEM); } - xp = xmlXPathNewContext(client->doc); + xpath.xp = xmlXPathNewContext(client->doc); - if (!xp) + if (!xpath.xp) { + xpath_command_cleanup(&xpath); return send_error(ctx, EPWMD_LIBXML_ERROR); + } - result = xmlXPathEvalExpression((xmlChar *)req[0], xp); + xpath.result = xmlXPathEvalExpression((xmlChar *)xpath.req[0], xpath.xp); - if (!result) { - xmlXPathFreeContext(xp); + if (!xpath.result) { + xpath_command_cleanup(&xpath); return send_error(ctx, EPWMD_LIBXML_ERROR); } - if (xmlXPathNodeSetIsEmpty(result->nodesetval)) { + if (xmlXPathNodeSetIsEmpty(xpath.result->nodesetval)) { rc = EPWMD_EMPTY_ELEMENT; goto fail; } - rc = recurse_xpath_nodeset(client->doc, result->nodesetval, - (xmlChar *)req[1], &buf); + rc = recurse_xpath_nodeset(client->doc, xpath.result->nodesetval, + (xmlChar *)xpath.req[1], &xpath.buf); if (rc) goto fail; - else if (!req[1] && !xmlBufferLength(buf)) { + else if (!xpath.req[1] && !xmlBufferLength(xpath.buf)) { rc = EPWMD_EMPTY_ELEMENT; goto fail; } - else if (req[1]) + else if (xpath.req[1]) goto fail; - rc = assuan_send_data(ctx, xmlBufferContent(buf), xmlBufferLength(buf)); + pthread_testcancel(); + rc = assuan_send_data(ctx, xmlBufferContent(xpath.buf), + xmlBufferLength(xpath.buf)); + pthread_testcancel(); fail: - g_strfreev(req); - - if (buf) - xmlBufferFree(buf); - - if (result) - xmlXPathFreeObject(result); - - if (xp) - xmlXPathFreeContext(xp); - + if (1) {} + pthread_cleanup_pop(1); return send_error(ctx, rc); } @@ -2594,7 +2673,9 @@ static int import_command(assuan_context_t ctx, gchar *line) if (rc) return send_error(ctx, rc); + pthread_testcancel(); rc = assuan_inquire_ext(ctx, "IMPORT", 0, import_command_finalize, ctx); + pthread_testcancel(); if (rc) return send_error(ctx, rc); @@ -2641,7 +2722,9 @@ static int getpid_command(assuan_context_t ctx, gchar *line) pid_t pid = getpid(); print_fmt(buf, sizeof(buf), "%i", pid); + pthread_testcancel(); rc = assuan_send_data(ctx, buf, strlen(buf)); + pthread_testcancel(); return send_error(ctx, rc); } @@ -2651,7 +2734,9 @@ static int version_command(assuan_context_t ctx, gchar *line) gchar buf[32]; print_fmt(buf, sizeof(buf), "%s", PACKAGE_VERSION); + pthread_testcancel(); rc = assuan_send_data(ctx, buf, strlen(buf)); + pthread_testcancel(); return send_error(ctx, rc); } diff --git a/src/pwmd.c b/src/pwmd.c index 5414097e..4de47997 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -134,6 +134,7 @@ gpg_error_t send_syserror(assuan_context_t ctx, gint e) { gpg_error_t n = gpg_error_from_errno(e); + pthread_testcancel(); return assuan_process_done(ctx, assuan_set_error(ctx, n, gpg_strerror(n))); } @@ -143,6 +144,8 @@ gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e) gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n); struct client_s *client = assuan_get_pointer(ctx); + pthread_testcancel(); + if (!e) return assuan_process_done(ctx, 0); @@ -862,8 +865,8 @@ static void *client_thread(void *data) break; case INQUIRE_DONE: cl->inquire_status = INQUIRE_INIT; - rc = assuan_process_done(cl->ctx, 0); pthread_testcancel(); + rc = assuan_process_done(cl->ctx, 0); break; } } @@ -2217,7 +2220,9 @@ int main(int argc, char *argv[]) textdomain("pwmd"); #endif +#ifndef MEM_DEBUG xmem_init(); +#endif gpg_err_init(); assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT); g_mem_set_vtable(&mtable); @@ -2582,6 +2587,8 @@ do_exit: #if defined(DEBUG) && !defined(MEM_DEBUG) xdump(); #endif +#ifndef MEM_DEBUG xmem_deinit(); +#endif exit(estatus); } -- 2.11.4.GIT