From 61b5da9c378d03f26ce5bc23e97bd1c5dd86f8e7 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sat, 7 Mar 2009 09:19:54 -0500 Subject: [PATCH] squash before commiting to master. this is the initial revert to v2 pthread ported to pth. --- configure.ac | 12 +- src/Makefile.am | 8 +- src/cache.c | 19 ++- src/cache.h | 12 +- src/commands.c | 206 +++++++++++-------------------- src/common.h | 31 ++--- src/lock.h | 33 +++-- src/mem.c | 78 ++++++++++-- src/mem.h | 4 +- src/pinentry.c | 74 +++++++----- src/pinentry.h | 4 +- src/pwmd.c | 366 +++++++++++++++++++++++++------------------------------- src/pwmd.h | 4 +- src/status.c | 265 +++++++++++++++++----------------------- src/tls.c | 4 +- 15 files changed, 525 insertions(+), 595 deletions(-) diff --git a/configure.ac b/configure.ac index aae778e5..5d0b9c11 100644 --- a/configure.ac +++ b/configure.ac @@ -20,6 +20,9 @@ case "$target_os" in ;; esac +enable_threads=set +gl_use_threads=pth + dnl Checks for programs. AC_PROG_AWK AC_PROG_LN_S @@ -34,15 +37,12 @@ dnl Checks for library functions. AM_PATH_GLIB_2_0(,, AC_MSG_ERROR([glib2 not found])) AM_PATH_LIBGCRYPT(,, AC_MSG_ERROR([libgcrypt not found])) AM_PATH_XML2(,, AC_MSG_ERROR([libxml2 not found])) -AM_PATH_LIBASSUAN(1.0.5,, AC_MSG_ERROR([libassuan not found])) +AM_PATH_LIBASSUAN_PTH(1.0.5,, AC_MSG_ERROR([libassuan-pth not found])) AM_PATH_GPG_ERROR(,, AC_MSG_ERROR([libgpg-error not found])) AC_CHECK_LIB(z, deflate,, AC_MSG_ERROR([Version 1.2.2.1 or later of zlib is required])) -ACX_PTHREAD(, [Missing or incomplete pthread installation]) - -LIBS="$PTHREAD_LIBS $LIBS" -CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -CC="$PTHREAD_CC" +AC_CHECK_PTH(, yes, yes, no, , + AC_MSG_ERROR([Missing or incomplete libpth installation])) AC_MSG_CHECKING([if zlib is >= 1.2.2.1]) AC_TRY_RUN([ diff --git a/src/Makefile.am b/src/Makefile.am index a3945ead..3c93593e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,13 +2,15 @@ bin_PROGRAMS = pwmd pwmd_SOURCES = pwmd.c pwmd.h xml.c xml.h pwmd_error.c pwmd_error.h commands.c \ commands.h common.h cache.c cache.h gettext.h misc.c misc.h \ status.c status.h lock.h -pwmd_LDFLAGS = @XML_LIBS@ @GLIB_LIBS@ @LIBGCRYPT_LIBS@ @GPG_ERROR_LIBS@ +pwmd_LDFLAGS = @XML_LIBS@ @GLIB_LIBS@ @LIBGCRYPT_LIBS@ @GPG_ERROR_LIBS@ \ + @PTH_LDFLAGS@ @PTH_LIBS@ pwmd_CFLAGS = -DLOCALEDIR=\"${prefix}/share/locale\" @XML_CPPFLAGS@ \ - @GLIB_CFLAGS@ @LIBGCRYPT_CFLAGS@ @GPG_ERROR_CFLAGS@ + @GLIB_CFLAGS@ @LIBGCRYPT_CFLAGS@ @GPG_ERROR_CFLAGS@ \ + @LIBASSUAN_PTH_CFLAGS@ @PTH_CFLAGS@ # It's a static library ATM, and linking will fail because _SOURCES is at the # end if the linker command line. -LIBS += @LIBASSUAN_LIBS@ +LIBS += @LIBASSUAN_PTH_LIBS@ if WITH_GNUTLS pwmd_SOURCES += tls.c tls.h diff --git a/src/cache.c b/src/cache.c index 921975f0..a4546e5a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -63,12 +63,12 @@ static file_cache_t *get_entry(const guchar *md5file) return NULL; } -gboolean cache_get_mutex(const guchar *md5file, struct file_mutex_s **result) +gboolean cache_get_mutex(const guchar *md5file, pth_mutex_t **result) { file_cache_t *p = get_entry(md5file); if (p) - *result = p->fmutex; + *result = p->mutex; return p ? TRUE : FALSE; } @@ -123,15 +123,15 @@ gboolean cache_add_file(const guchar *md5file, const guchar *shakey) return FALSE; } - p->fmutex = g_malloc(sizeof(struct file_mutex_s)); + p->mutex = g_malloc(sizeof(pth_mutex_t)); - if (!p->fmutex) { + if (!p->mutex) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM)); g_free(p); return FALSE; } - pthread_mutex_init(&p->fmutex->mutex, NULL); + pth_mutex_init(p->mutex); memcpy(p->filename, md5file, sizeof(p->filename)); if (shakey) @@ -146,8 +146,7 @@ gboolean cache_add_file(const guchar *md5file, const guchar *shakey) if (!new) { log_write("%s(%i): %s", __FUNCTION__, __LINE__, strerror(ENOMEM)); - pthread_mutex_destroy(&p->fmutex->mutex); - g_free(p->fmutex); + g_free(p->mutex); memset(p, 0, sizeof(file_cache_t)); g_free(p); return FALSE; @@ -162,10 +161,8 @@ static void free_entry(file_cache_t *p) if (!p) return; - if (p->fmutex) { - pthread_mutex_destroy(&p->fmutex->mutex); - g_free(p->fmutex); - } + if (p->mutex) + g_free(p->mutex); memset(p, 0, sizeof(file_cache_t)); munlock(p, sysconf(_SC_PAGESIZE)); diff --git a/src/cache.h b/src/cache.h index ec09f10d..d7e3aad8 100644 --- a/src/cache.h +++ b/src/cache.h @@ -19,25 +19,21 @@ #ifndef CACHE_H #define CACHE_H -#include +#include #include #include "status.h" -struct file_mutex_s { - pthread_mutex_t mutex; -}; - typedef struct { guchar filename[16]; /* MD5 hash. */ guchar key[32]; /* SHA256/AES256/gcrykeysize */ glong timeout; /* adjust_cache_time_thread(). */ glong reset; /* To reset .timeout. */ - struct file_mutex_s *fmutex; + pth_mutex_t *mutex; gint refcount; /* The number of associated clients. */ } file_cache_t; GSList *key_cache; -pthread_mutex_t cache_mutex; +pth_mutex_t cache_mutex; void cache_adjust_timer(void); gboolean cache_set_timeout(const guchar *md5filename, glong timeout); @@ -49,7 +45,7 @@ gboolean cache_get_key(const guchar *md5file, guchar *shakey); gboolean cache_update_key(const guchar *md5filename, const guchar *shakey); gint cache_file_count(void); gboolean cache_has_file(const guchar *md5file); -gboolean cache_get_mutex(const guchar *md5filename, struct file_mutex_s **result); +gboolean cache_get_mutex(const guchar *md5filename, pth_mutex_t **result); gboolean cache_decr_refcount(const guchar *md5filename); gboolean cache_incr_refcount(const guchar *md5filename); void cache_free(); diff --git a/src/commands.c b/src/commands.c index d625251c..32101baa 100644 --- a/src/commands.c +++ b/src/commands.c @@ -85,7 +85,7 @@ static gpg_error_t file_modified(struct client_s *client) return EPWMD_FILE_MODIFIED; } - pthread_testcancel(); + pth_cancel_point(); return 0; } @@ -103,7 +103,7 @@ static gpg_error_t parse_xml(assuan_context_t ctx) void unlock_file_mutex(struct client_s *client) { - struct file_mutex_s *m; + pth_mutex_t *m; #ifdef WITH_PINENTRY if (client->has_lock == FALSE || client->pinentry->status != PINENTRY_NONE) @@ -120,13 +120,13 @@ void unlock_file_mutex(struct client_s *client) } CACHE_UNLOCK; - MUTEX_UNLOCK(&m->mutex); + MUTEX_UNLOCK(m); client->has_lock = client->is_lock_cmd = FALSE; } gpg_error_t lock_file_mutex(struct client_s *client) { - struct file_mutex_s *m; + pth_mutex_t *m; if (client->has_lock == TRUE) return 0; @@ -140,25 +140,25 @@ gpg_error_t lock_file_mutex(struct client_s *client) CACHE_UNLOCK; - if (pthread_mutex_trylock(&m->mutex) == EBUSY) { + if (pth_mutex_acquire(m, TRUE, NULL) == EBUSY) { if (client->ctx) { /* * If a client disconnects unexpectedly while waiting for a * lock, this lets the thread terminate because send_status() * will return an error. */ - while (pthread_mutex_trylock(&m->mutex) == EBUSY) { + while (pth_mutex_acquire(m, TRUE, NULL) == EBUSY) { gpg_error_t rc = send_status(client->ctx, STATUS_LOCKED, NULL); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; - sleep(1); + pth_sleep(1); } } else { - MUTEX_LOCK(&m->mutex); + MUTEX_LOCK(m); } } else { @@ -259,7 +259,6 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, } 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; @@ -325,12 +324,8 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, 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", gz->z.total_out, insize); - pthread_testcancel(); - pthread_cleanup_pop(0); if (*rc) goto fail; @@ -344,10 +339,10 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, } } while (*rc != Z_STREAM_END); - pthread_testcancel(); + pth_cancel_point(); *rc = send_status(ctx, STATUS_DECOMPRESS, "%li %li", gz->z.total_out, insize); - pthread_testcancel(); + pth_cancel_point(); if (*rc) goto fail; @@ -361,15 +356,10 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gulong insize, fail: log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); - pthread_cleanup_pop(1); + gz_cleanup(&gz); return FALSE; } -static void read_file_header_handler(void *arg) -{ - close((int)arg); -} - file_header_internal_t *read_file_header(const gchar *filename, gboolean v1, gpg_error_t *rc) { @@ -409,15 +399,14 @@ file_header_internal_t *read_file_header(const gchar *filename, gboolean v1, } if (v1) - len = read(fd, &fh->fh1, fh_size); + len = pth_read(fd, &fh->fh1, fh_size); else - len = read(fd, &fh->fh2, fh_size); + len = pth_read(fd, &fh->fh2, fh_size); if (len != fh_size) { gint n = errno; - pthread_cleanup_push(read_file_header_handler, (void *)fd); + close(fd); g_free(fh); - pthread_cleanup_pop(1); *rc = gpg_error_from_errno(n); return NULL; } @@ -561,8 +550,6 @@ static int open_command(assuan_context_t ctx, char *line) if ((req = split_input_line(line, " ", 2)) != NULL) filename = req[0]; - pthread_cleanup_push(req_cleanup, req); - if (!filename || !*filename) { g_strfreev(req); return send_error(ctx, EPWMD_COMMAND_SYNTAX); @@ -627,7 +614,7 @@ static int open_command(assuan_context_t ctx, char *line) memset(client->crypto->key, 0, gcrykeysize); client->crypto->fh = read_file_header(filename, FALSE, &rc); - pthread_testcancel(); + pth_cancel_point(); if (!client->crypto->fh) { if (gpg_err_code_to_errno(rc) != ENOENT) { @@ -776,8 +763,7 @@ static int open_command(assuan_context_t ctx, char *line) } done: - if (1) {} - pthread_cleanup_pop(1); + req_cleanup(req); return open_command_finalize(ctx, client->crypto->key, cached); } @@ -797,7 +783,6 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, } 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; @@ -864,12 +849,8 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, else gz->z.avail_in = zlib_bufsize; - pthread_cleanup_push(gz_cleanup, &gz); - pthread_testcancel(); *rc = send_status(ctx, STATUS_COMPRESS, "%li %li", gz->z.total_in, size); - pthread_testcancel(); - pthread_cleanup_pop(0); if (*rc) goto fail; @@ -886,9 +867,9 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, } } while (*rc != Z_STREAM_END); - pthread_testcancel(); + pth_cancel_point(); *rc = send_status(ctx, STATUS_COMPRESS, "%li %li", gz->z.total_in, size); - pthread_testcancel(); + pth_cancel_point(); if (*rc) goto fail; @@ -902,7 +883,7 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, fail: log_write("%s(%i): %s", __FUNCTION__, __LINE__, gz->z.msg); - pthread_cleanup_pop(1); + gz_cleanup(&gz); return FALSE; } @@ -920,8 +901,6 @@ static gpg_error_t iterate_crypto_once(struct client_s *client, if (!p) return gpg_err_code_from_errno(ENOMEM); - pthread_cleanup_push(gcry_free, p); - if (crypto->insize < CRYPTO_BLOCKSIZE) len = crypto->insize; @@ -947,12 +926,11 @@ static gpg_error_t iterate_crypto_once(struct client_s *client, if (total >= crypto->insize) break; - pthread_testcancel(); + pth_cancel_point(); } done: - if (1) {} - pthread_cleanup_pop(1); + gcry_free(p); return rc; } @@ -1022,7 +1000,7 @@ gpg_error_t do_xml_encrypt(struct client_s *client, if (iter_progress && crypto->fh->fh2.iter >= iter_progress) { rc = send_status(client ? client->ctx : NULL, STATUS_ENCRYPT, "0 %llu", crypto->fh->fh2.iter); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; @@ -1034,7 +1012,7 @@ gpg_error_t do_xml_encrypt(struct client_s *client, rc = send_status(client ? client->ctx : NULL, STATUS_ENCRYPT, "%llu %llu", ++n_iter * iter_progress, crypto->fh->fh2.iter); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; @@ -1076,7 +1054,7 @@ gpg_error_t do_xml_encrypt(struct client_s *client, if (iter_progress && crypto->fh->fh2.iter >= iter_progress) { rc = send_status(client ? client->ctx : NULL, STATUS_ENCRYPT, "%llu %llu", crypto->fh->fh2.iter, crypto->fh->fh2.iter); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; @@ -1090,7 +1068,7 @@ write_file: } if (lstat(filename, &st) == 0) { - pthread_testcancel(); + pth_cancel_point(); mode = st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO); /* @@ -1100,7 +1078,7 @@ write_file: return gpg_error_from_errno(EACCES); } else { - pthread_testcancel(); + pth_cancel_point(); if (errno != ENOENT) return gpg_error_from_errno(errno); } @@ -1124,8 +1102,8 @@ write_file: do_write_file: crypto->fh->fh2.version = VERSION_HEX; - len = write(crypto->fh->fd, &crypto->fh->fh2, sizeof(crypto->fh->fh2)); - pthread_testcancel(); + len = pth_write(crypto->fh->fd, &crypto->fh->fh2, sizeof(crypto->fh->fh2)); + pth_cancel_point(); if (len != sizeof(crypto->fh->fh2)) { len = errno; @@ -1136,23 +1114,23 @@ do_write_file: return gpg_error_from_errno(len); } - len = write(crypto->fh->fd, crypto->inbuf, crypto->insize); - pthread_testcancel(); + len = pth_write(crypto->fh->fd, crypto->inbuf, crypto->insize); + pth_cancel_point(); if (len != crypto->insize) { - pthread_testcancel(); + pth_cancel_point(); len = errno; if (filename && strcmp(filename, "-")) { unlink(tmp); - pthread_testcancel(); + pth_cancel_point(); } return gpg_error_from_errno(len); } if (fsync(crypto->fh->fd) == -1) { - pthread_testcancel(); + pth_cancel_point(); len = errno; if (filename && strcmp(filename, "-")) @@ -1168,7 +1146,7 @@ do_write_file: g_snprintf(tmp2, sizeof(tmp2), "%s.backup", filename); if (rename(filename, tmp2) == -1) { - pthread_testcancel(); + pth_cancel_point(); unlink(tmp); len = errno; return gpg_error_from_errno(len); @@ -1176,7 +1154,7 @@ do_write_file: } if (rename(tmp, filename) == -1) { - pthread_testcancel(); + pth_cancel_point(); len = errno; unlink(tmp); return gpg_error_from_errno(len); @@ -1184,14 +1162,14 @@ do_write_file: if (mode) { chmod(filename, mode); - pthread_testcancel(); + pth_cancel_point(); } } if (client && lstat(filename, &st) == 0) client->mtime = st.st_mtime; - pthread_testcancel(); + pth_cancel_point(); return 0; } @@ -1534,9 +1512,9 @@ static int store_command(assuan_context_t ctx, char *line) if (rc) return send_error(ctx, rc); - pthread_testcancel(); + pth_cancel_point(); rc = assuan_inquire_ext(ctx, "STORE", 0, store_command_finalize, ctx); - pthread_testcancel(); + pth_cancel_point(); if (rc) return send_error(ctx, rc); @@ -1588,9 +1566,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(); + pth_cancel_point(); rc = assuan_send_data(ctx, n->content, xmlStrlen(n->content)); - pthread_testcancel(); + pth_cancel_point(); return send_error(ctx, rc); } @@ -1712,11 +1690,8 @@ again: } } - pthread_cleanup_push(list_command_cleanup1, string); - pthread_testcancel(); rc = assuan_send_data(ctx, string->str, string->len); - pthread_testcancel(); - pthread_cleanup_pop(1); + list_command_cleanup1(string); return send_error(ctx, rc); } @@ -1766,15 +1741,12 @@ 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); - pthread_testcancel(); - pthread_cleanup_pop(1); + list_command_cleanup1(str); return send_error(ctx, rc); } @@ -1786,10 +1758,7 @@ 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; @@ -1812,24 +1781,19 @@ 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); - pthread_testcancel(); - pthread_cleanup_pop(1); + list_command_cleanup1(str); } else rc = EPWMD_EMPTY_ELEMENT; fail: - if (1) {} - pthread_cleanup_pop(1); + list_command_cleanup2(elements); return send_error(ctx, rc); } @@ -1929,13 +1893,9 @@ 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)); - pthread_testcancel(); - pthread_cleanup_pop(1); - pthread_cleanup_pop(1); + g_free(line); + req_cleanup(attrlist); return rc; } @@ -2254,11 +2214,8 @@ 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)); - pthread_testcancel(); - pthread_cleanup_pop(1); + xmlFree(a); return rc; fail: @@ -2347,8 +2304,6 @@ 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) @@ -2360,7 +2315,7 @@ static int attr_command(assuan_context_t ctx, char *line) else rc = EPWMD_COMMAND_SYNTAX; - pthread_cleanup_pop(1); + req_cleanup(req); return send_error(ctx, rc); } @@ -2376,7 +2331,6 @@ 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) { @@ -2385,7 +2339,6 @@ static int iscached_command(assuan_context_t ctx, char *line) } CACHE_UNLOCK; - pthread_cleanup_pop(0); return send_error(ctx, 0); } @@ -2395,7 +2348,6 @@ 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) { @@ -2414,7 +2366,6 @@ static int clearcache_command(assuan_context_t ctx, char *line) } CACHE_UNLOCK; - pthread_cleanup_pop(0); return send_error(ctx, 0); } @@ -2426,8 +2377,6 @@ 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); @@ -2442,8 +2391,6 @@ static int cachetimeout_command(assuan_context_t ctx, char *line) } gcry_md_hash_buffer(GCRY_MD_MD5, md5file, req[1], strlen(req[1])); - pthread_cleanup_pop(1); - pthread_cleanup_push(pthread_mutex_unlock, (void *)&cache_mutex); CACHE_LOCK(client->ctx); if (cache_set_timeout(md5file, timeout) == FALSE) { @@ -2452,7 +2399,6 @@ static int cachetimeout_command(assuan_context_t ctx, char *line) } CACHE_UNLOCK; - pthread_cleanup_pop(0); return send_error(ctx, 0); } @@ -2478,11 +2424,8 @@ 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); - pthread_testcancel(); - pthread_cleanup_pop(1); + xmlFree(xml); return send_error(ctx, rc); } @@ -2524,11 +2467,8 @@ 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)); - pthread_testcancel(); - pthread_cleanup_pop(1); + g_free(p); return send_error(ctx, rc); } @@ -2573,7 +2513,6 @@ static int xpath_command(assuan_context_t ctx, gchar *line) return send_error(ctx, EPWMD_COMMAND_SYNTAX); 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) @@ -2611,14 +2550,13 @@ static int xpath_command(assuan_context_t ctx, gchar *line) else if (xpath.req[1]) goto fail; - pthread_testcancel(); + pth_cancel_point(); rc = assuan_send_data(ctx, xmlBufferContent(xpath.buf), xmlBufferLength(xpath.buf)); - pthread_testcancel(); + pth_cancel_point(); fail: - if (1) {} - pthread_cleanup_pop(1); + xpath_command_cleanup(&xpath); return send_error(ctx, rc); } @@ -2749,9 +2687,9 @@ static int import_command(assuan_context_t ctx, gchar *line) if (rc) return send_error(ctx, rc); - pthread_testcancel(); + pth_cancel_point(); rc = assuan_inquire_ext(ctx, "IMPORT", 0, import_command_finalize, ctx); - pthread_testcancel(); + pth_cancel_point(); if (rc) return send_error(ctx, rc); @@ -2798,9 +2736,9 @@ static int getpid_command(assuan_context_t ctx, gchar *line) pid_t pid = getpid(); print_fmt(buf, sizeof(buf), "%i", pid); - pthread_testcancel(); + pth_cancel_point(); rc = assuan_send_data(ctx, buf, strlen(buf)); - pthread_testcancel(); + pth_cancel_point(); return send_error(ctx, rc); } @@ -2810,9 +2748,9 @@ static int version_command(assuan_context_t ctx, gchar *line) gchar buf[32]; print_fmt(buf, sizeof(buf), "%s", PACKAGE_VERSION); - pthread_testcancel(); + pth_cancel_point(); rc = assuan_send_data(ctx, buf, strlen(buf)); - pthread_testcancel(); + pth_cancel_point(); return send_error(ctx, rc); } @@ -2850,13 +2788,13 @@ static gpg_error_t parse_client_option(assuan_context_t ctx, const gchar *line) return gpg_err_make(PWMD_ERR_SOURCE, GPG_ERR_SYNTAX); if (g_strcasecmp(name, (gchar *)"NAME") == 0) { - struct client_s *cl = assuan_get_pointer(ctx); - - if (cl->thd->name) - g_free(cl->thd->name); + pth_attr_t attr = pth_attr_of(pth_self()); + gchar buf[41]; - cl->thd->name = g_strdup(value); - log_write("OPTION CLIENT %s", line); + print_fmt(buf, sizeof(buf), "%s", value); + pth_attr_set(attr, PTH_ATTR_NAME, buf); + pth_attr_destroy(attr); + log_write("OPTION CLIENT %s=%s", name, buf); } else return gpg_err_make(PWMD_ERR_SOURCE, GPG_ERR_UNKNOWN_OPTION); @@ -3056,8 +2994,8 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, guchar *key, } crypto->insize = insize; - len = read(crypto->fh->fd, crypto->inbuf, crypto->insize); - pthread_testcancel(); + len = pth_read(crypto->fh->fd, crypto->inbuf, crypto->insize); + pth_cancel_point(); if (len != crypto->insize) return GPG_ERR_INV_LENGTH; @@ -3080,7 +3018,7 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, guchar *key, if (iter_progress > 0 && fh_iter >= iter_progress) { rc = send_status(ctx, STATUS_DECRYPT, "0 %llu", fh_iter); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; @@ -3112,7 +3050,7 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, guchar *key, if (!(iter % iter_progress)) { rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", ++n_iter * iter_progress, fh_iter); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; @@ -3136,7 +3074,7 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, guchar *key, if (iter_progress && fh_iter >= iter_progress) { rc = send_status(ctx, STATUS_DECRYPT, "%llu %llu", fh_iter, fh_iter); - pthread_testcancel(); + pth_cancel_point(); if (rc) return rc; diff --git a/src/common.h b/src/common.h index 7115e073..12626f0b 100644 --- a/src/common.h +++ b/src/common.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #define _ASSUAN_ONLY_GPG_ERRORS 1 @@ -80,10 +80,10 @@ typedef struct { typedef gpg_error_t (*pinentry_finalize_cb)(assuan_context_t, guchar *, gboolean); struct pinentry_s { - pthread_t tid; - pthread_mutex_t status_mutex; - pthread_mutex_t cond_mutex; - pthread_cond_t cond; + pth_t tid; + pth_mutex_t status_mutex; + pth_mutex_t cond_mutex; + pth_cond_t cond; pinentry_cmd_t which; gchar *filename; assuan_context_t ctx; @@ -136,23 +136,17 @@ typedef struct { } file_header_internal_t; struct client_thread_s { - pthread_t tid; - GSList *msg_queue; - pthread_t msg_tid; - pthread_cond_t msg_cond; - pthread_t msg_sender_tid; - pthread_cond_t msg_sender_cond; - pthread_mutex_t msg_sender_mutex; - status_msg_t msg; - gint msg_fd[2]; - gchar *name; + pth_t tid; + GSList *msg_list; + pth_mutex_t msg_list_mutex; + pth_t msg_tid; + pth_cond_t msg_cond; gint fd; struct client_s *cl; #ifdef WITH_GNUTLS gboolean remote; struct tls_s *tls; #endif - gboolean quit; }; struct status_msg_s { @@ -193,14 +187,15 @@ struct client_s { inquire_status_t inquire_status; struct client_thread_s *thd; struct client_crypto_s *crypto; + status_msg_t msg; /* the current message being sent. */ }; gsize gcrykeysize, gcryblocksize; GKeyFile *keyfileh; gboolean log_syslog; gint zlib_bufsize; -pthread_mutex_t rcfile_mutex; -pthread_mutex_t cn_mutex; +pth_mutex_t rcfile_mutex; +pth_mutex_t cn_mutex; GSList *cn_thread_list; void log_write(const gchar *fmt, ...); diff --git a/src/lock.h b/src/lock.h index fd03ae96..151a025e 100644 --- a/src/lock.h +++ b/src/lock.h @@ -19,7 +19,8 @@ #ifndef LOCK_H #define LOCK_H -#include +#include +#include #include #include "cache.h" @@ -37,18 +38,32 @@ #define CACHE_UNLOCK MUTEX_UNLOCK(&cache_mutex) #define MUTEX_LOCK(m) \ - MUTEX_LOCK_DEBUG pthread_mutex_lock(m) + MUTEX_LOCK_DEBUG \ + if (pth_mutex_acquire(m, FALSE, NULL) == FALSE) { \ + log_write("%s(%i): %s: UNLOCK", __FILE__, __LINE__, __FUNCTION__); \ + assert(0); \ + } #define MUTEX_UNLOCK(m) \ - MUTEX_UNLOCK_DEBUG pthread_mutex_unlock(m) + MUTEX_UNLOCK_DEBUG \ + if (pth_mutex_release(m) == FALSE) { \ + log_write("%s(%i): %s: UNLOCK", __FILE__, __LINE__, __FUNCTION__); \ + assert(0); \ + } #define MUTEX_TRYLOCK(ctx, m) \ - if (pthread_mutex_trylock(m) == EBUSY) { \ - if (ctx) \ - send_status(ctx, STATUS_LOCKED, NULL); \ - log_write(N_("%s(%i): %s: mutex is LOCKED"), __FILE__, __LINE__, \ - __FUNCTION__); \ - MUTEX_LOCK(m); \ + if (pth_mutex_acquire(m, TRUE, NULL) == FALSE) { \ + if (errno == EBUSY) { \ + if (ctx) \ + send_status(ctx, STATUS_LOCKED, NULL); \ + log_write(N_("%s(%i): %s: mutex is LOCKED"), __FILE__, __LINE__, \ + __FUNCTION__); \ + MUTEX_LOCK(m); \ + } \ + else { \ + log_write("%s(%i): %s: UNLOCK", __FILE__, __LINE__, __FUNCTION__); \ + assert(0); \ + } \ } \ else { \ MUTEX_LOCK_DEBUG \ diff --git a/src/mem.c b/src/mem.c index 5fdcc54b..0ceebd57 100644 --- a/src/mem.c +++ b/src/mem.c @@ -22,19 +22,28 @@ #include #include #include -#include #ifdef HAVE_CONFIG_H #include #endif +#include "mem.h" + +#ifdef USE_PTH_THREADS +#include +#else +#include +#endif + #include "gettext.h" #define N_(msgid) gettext(msgid) -#include "mem.h" - static struct memlist_s *memlist; +#ifdef USE_PTH_THREADS +static pth_mutex_t mem_mutex; +#else static pthread_mutex_t mem_mutex; +#endif #ifdef DEBUG static size_t allocations, deallocations; #endif @@ -44,21 +53,24 @@ void xmem_init() static int init; if (!init) - pthread_mutex_init(&mem_mutex, NULL); +#ifdef USE_PTH_THREADS + pth_mutex_init(&mem_mutex); +#else + pthread_mutex_init(&mem_mutex, NULL); +#endif init = 1; } -void xmem_deinit() -{ - pthread_mutex_destroy(&mem_mutex); -} - static int memlist_remove(void *ptr, const char *func) { struct memlist_s *m, *last = NULL, *p; +#ifdef USE_PTH_THREADS + pth_mutex_acquire(&mem_mutex, FALSE, NULL); +#else pthread_mutex_lock(&mem_mutex); +#endif for (m = memlist; m; m = m->next) { if (m->ptr == ptr) { @@ -79,26 +91,42 @@ static int memlist_remove(void *ptr, const char *func) else memlist = p; +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif return 1; } last = m; } +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif return 0; } static void memlist_prepend(struct memlist_s *new) { +#ifdef USE_PTH_THREADS + pth_mutex_acquire(&mem_mutex, FALSE, NULL); +#else pthread_mutex_lock(&mem_mutex); +#endif #ifdef DEBUG allocations++; #endif new->next = memlist; memlist = new; +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif } void xfree(void *ptr) @@ -173,12 +201,20 @@ void *xrealloc(void *ptr, size_t size) if (!ptr) return xmalloc(size); +#ifdef USE_PTH_THREADS + pth_mutex_acquire(&mem_mutex, FALSE, NULL); +#else pthread_mutex_lock(&mem_mutex); +#endif for (m = memlist; m; m = m->next) { if (m->ptr == ptr) { if ((p = (void *)malloc(size)) == NULL) { +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif return NULL; } @@ -190,13 +226,21 @@ void *xrealloc(void *ptr, size_t size) #ifdef DEBUG fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size); #endif +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif return m->ptr; } } warnx(N_("%s: %p not found"), __FUNCTION__, ptr); +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif assert(0); return NULL; } @@ -229,12 +273,20 @@ void xpanic(void) { struct memlist_s *m; +#ifdef USE_PTH_THREADS + pth_mutex_acquire(&mem_mutex, FALSE, NULL); +#else pthread_mutex_lock(&mem_mutex); +#endif for (m = memlist; m; m = memlist) xfree(m->ptr); +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif } #ifdef DEBUG @@ -243,7 +295,11 @@ void xdump(void) struct memlist_s *m; size_t total = 0; +#ifdef USE_PTH_THREADS + pth_mutex_acquire(&mem_mutex, FALSE, NULL); +#else pthread_mutex_lock(&mem_mutex); +#endif for (m = memlist; m; m = m->next) { fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size); @@ -252,6 +308,10 @@ void xdump(void) fprintf(stderr, "Total unfreed: %i bytes, allocations: %i, deallocations: %i\n", total, allocations, deallocations); +#ifdef USE_PTH_THREADS + pth_mutex_release(&mem_mutex); +#else pthread_mutex_unlock(&mem_mutex); +#endif } #endif diff --git a/src/mem.h b/src/mem.h index e59bcafc..bdb06728 100644 --- a/src/mem.h +++ b/src/mem.h @@ -1,6 +1,6 @@ /* vim:tw=78:ts=8:sw=4:set ft=c: */ /* - Copyright (C) 2007 Ben Kibbey + Copyright (C) 2007-2009 Ben Kibbey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ extern "C" { #endif +#define USE_PTH_THREADS 1 #ifdef MEM_DEBUG #define xfree free #define xmalloc malloc @@ -38,7 +39,6 @@ struct memlist_s { }; void xmem_init(void); -void xmem_deinit(void); void xfree(void *ptr) __attribute__ ((visibility ("hidden"))); void *xmalloc(size_t size) __attribute__ ((visibility ("hidden"))); void *xrealloc(void *ptr, size_t size) __attribute__ ((visibility ("hidden"))); diff --git a/src/pinentry.c b/src/pinentry.c index c0413456..c1f52e37 100644 --- a/src/pinentry.c +++ b/src/pinentry.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -381,7 +381,7 @@ static int write_result(int fd, pinentry_key_s *pk, char *result) if (gpg_err_code(pk->error) == GPG_ERR_EOF) pk->error = GPG_ERR_CANCELED; - len = write(fd, pk, sizeof(pinentry_key_s)); + len = pth_write(fd, pk, sizeof(pinentry_key_s)); close(fd); if (len != sizeof(pinentry_key_s)) @@ -396,7 +396,7 @@ static int write_result(int fd, pinentry_key_s *pk, char *result) g_strlcpy(pk->what.key, result, sizeof(pk->what.key)); xfree(result); - len = write(fd, pk, sizeof(pinentry_key_s)); + len = pth_write(fd, pk, sizeof(pinentry_key_s)); if (len != sizeof(pinentry_key_s)) { memset(pk, 0, sizeof(pinentry_key_s)); @@ -442,21 +442,32 @@ static void kill_pinentry(struct pinentry_s *pin) pin->pin_pid = 0; } +static void timeout_cleanup(void *arg) +{ + pth_event_t ev = arg; + + pth_event_free(ev, PTH_FREE_ALL); +} + static void *timeout_thread(void *arg) { struct pinentry_s *pin = arg; - struct timespec ts; + pth_event_t ev; + pth_attr_t attr = pth_attr_of(pth_self()); - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += pin->timeout; + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); + ev = pth_event(PTH_EVENT_TIME, pth_timeout(pin->timeout, 0)); MUTEX_LOCK(&pin->cond_mutex); - pthread_cond_timedwait(&pin->cond, &pin->cond_mutex, &ts); + pth_cleanup_push(timeout_cleanup, ev); + pth_cond_await(&pin->cond, &pin->cond_mutex, ev); + pth_cleanup_pop(1); - /* pthread_cond_signal() was called from pinentry_iterate() (we have a + /* pth_cond_notify() was called from pinentry_iterate() (we have a * key). */ if (pin->status == PINENTRY_NONE) { MUTEX_UNLOCK(&pin->cond_mutex); - pthread_exit(PTHREAD_CANCELED); + pth_exit(PTH_CANCELED); return NULL; } @@ -465,7 +476,7 @@ static void *timeout_thread(void *arg) pin->status = PINENTRY_TIMEOUT; MUTEX_UNLOCK(&pin->cond_mutex); MUTEX_UNLOCK(&pin->status_mutex); - pthread_exit(PTHREAD_CANCELED); + pth_exit(PTH_CANCELED); return NULL; } @@ -482,7 +493,7 @@ gpg_error_t pinentry_fork(assuan_context_t ctx) if (pipe(p) == -1) return gpg_error_from_syserror(); - pid = fork(); + pid = pth_fork(); switch (pid) { case -1: @@ -531,20 +542,20 @@ gpg_error_t pinentry_fork(assuan_context_t ctx) gpg_error_t lock_pin_mutex(struct client_s *client) { - if (pthread_mutex_trylock(&pin_mutex) == EBUSY) { + if (pth_mutex_acquire(&pin_mutex, TRUE, NULL) == EBUSY) { if (client->ctx) { /* * If a client disconnects unexpectedly while waiting for a * lock, this lets the thread terminate because send_status() * will return an error. */ - while (pthread_mutex_trylock(&pin_mutex) == EBUSY) { + while (pth_mutex_acquire(&pin_mutex, TRUE, NULL) == EBUSY) { gpg_error_t rc = send_status(client->ctx, STATUS_LOCKED, NULL); if (rc) return rc; - sleep(1); + pth_sleep(1); } } else @@ -574,26 +585,23 @@ void cleanup_pinentry(struct pinentry_s *pin) if (pin->ctx && pin->pid) pinentry_disconnect(pin); - if (pthread_mutex_trylock(&pin->status_mutex) == EBUSY) { + if (pth_mutex_acquire(&pin->status_mutex, TRUE, NULL) == EBUSY) { MUTEX_UNLOCK(&pin->status_mutex); } else - pthread_mutex_unlock(&pin->status_mutex); + pth_mutex_release(&pin->status_mutex); MUTEX_LOCK(&pin->status_mutex); kill_pinentry(pin); MUTEX_UNLOCK(&pin->status_mutex); unlock_pin_mutex(pin); - pthread_mutex_destroy(&pin->status_mutex); - if (pthread_mutex_trylock(&pin->cond_mutex) == EBUSY) { + if (pth_mutex_acquire(&pin->cond_mutex, TRUE, NULL) == EBUSY) { MUTEX_UNLOCK(&pin->cond_mutex); } else - pthread_mutex_unlock(&pin->cond_mutex); + pth_mutex_release(&pin->cond_mutex); - pthread_mutex_destroy(&pin->cond_mutex); - pthread_cond_destroy(&pin->cond); g_free(pin->ttyname); g_free(pin->ttytype); g_free(pin->desc); @@ -674,8 +682,8 @@ int pinentry_iterate(struct client_s *cl, gboolean read_ready) gsize len; memset(&pk, 0, sizeof(pk)); - len = read(cl->pinentry->fd, &pk, sizeof(pk)); - pthread_testcancel(); + len = pth_read(cl->pinentry->fd, &pk, sizeof(pk)); + pth_cancel_point(); if (len == sizeof(pk)) { if (pk.error) { @@ -689,18 +697,18 @@ int pinentry_iterate(struct client_s *cl, gboolean read_ready) * Start the timeout thread for the pinentry process * now that we know the pid of it. */ - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pth_attr_t attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); cl->pinentry->pin_pid = pk.what.pid; - pthread_create(&cl->pinentry->tid, &attr, timeout_thread, + cl->pinentry->tid = pth_spawn(attr, timeout_thread, cl->pinentry); - pthread_attr_destroy(&attr); + pth_attr_destroy(attr); } else { if (cl->pinentry->tid) { cl->pinentry->status = PINENTRY_NONE; - pthread_cond_signal(&cl->pinentry->cond); + pth_cond_notify(&cl->pinentry->cond, FALSE); } shakey = gcry_malloc(gcrykeysize); @@ -735,7 +743,7 @@ int pinentry_iterate(struct client_s *cl, gboolean read_ready) if (pk.error) { if (cl->pinentry->tid) { cl->pinentry->status = PINENTRY_NONE; - pthread_cond_signal(&cl->pinentry->cond); + pth_cond_notify(&cl->pinentry->cond, FALSE); } if (cl->pinentry->which == PINENTRY_OPEN) @@ -763,9 +771,9 @@ struct pinentry_s *pinentry_init() if (!pin) return NULL; - pthread_mutex_init(&pin->status_mutex, NULL); - pthread_mutex_init(&pin->cond_mutex, NULL); - pthread_cond_init(&pin->cond, NULL); + pth_mutex_init(&pin->status_mutex); + pth_mutex_init(&pin->cond_mutex); + pth_cond_init(&pin->cond); set_pinentry_defaults(pin); return pin; } diff --git a/src/pinentry.h b/src/pinentry.h index 0efede11..387bd7a2 100644 --- a/src/pinentry.h +++ b/src/pinentry.h @@ -19,9 +19,9 @@ #ifndef PINENTRY_H #define PINENTRY_H -#include +#include -pthread_mutex_t pin_mutex; +pth_mutex_t pin_mutex; gpg_error_t pinentry_fork(assuan_context_t ctx); void cleanup_pinentry(struct pinentry_s *pin); diff --git a/src/pwmd.c b/src/pwmd.c index 579f0aeb..630bab94 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -72,7 +72,7 @@ #include "pwmd.h" #include "lock.h" -GCRY_THREAD_OPTION_PTHREAD_IMPL; +GCRY_THREAD_OPTION_PTH_IMPL; static void clear_rcfile_keys() { @@ -96,8 +96,11 @@ static void *reload_rcfile_thread(void *arg) { gboolean b = disable_list_and_dump; GKeyFile *k; + pth_attr_t attr = pth_attr_of(pth_self()); - pthread_mutex_lock(&rcfile_mutex); + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); + pth_mutex_acquire(&rcfile_mutex, FALSE, NULL); log_write(N_("reloading configuration file '%s'"), rcfile); k = parse_rcfile(FALSE); @@ -115,26 +118,26 @@ static void *reload_rcfile_thread(void *arg) startStopKeepAlive(FALSE); send_status_all(STATUS_CONFIG); done: - pthread_mutex_unlock(&rcfile_mutex); + pth_mutex_release(&rcfile_mutex); return NULL; } static void reload_rcfile() { - pthread_t tid; - pthread_attr_t attr; + pth_t tid; + pth_attr_t attr = pth_attr_new(); - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&tid, &attr, reload_rcfile_thread, NULL); - pthread_attr_destroy(&attr); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, 0); + tid = pth_spawn(attr, reload_rcfile_thread, NULL); + pth_attr_destroy(attr); } gpg_error_t send_syserror(assuan_context_t ctx, gint e) { gpg_error_t n = gpg_error_from_errno(e); - pthread_testcancel(); + pth_cancel_point(); return assuan_process_done(ctx, assuan_set_error(ctx, n, gpg_strerror(n))); } @@ -144,7 +147,7 @@ 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(); + pth_cancel_point(); if (!e) return assuan_process_done(ctx, 0); @@ -175,23 +178,6 @@ gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e) return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e))); } -static struct client_thread_s *find_cn(pthread_t tid) -{ - guint t, i; - - if (!cn_thread_list) - return NULL; - - for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) { - struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i); - - if (cn->tid == tid) - return cn; - } - - return NULL; -} - void log_write(const gchar *fmt, ...) { gchar *args, *line; @@ -200,9 +186,10 @@ void log_write(const gchar *fmt, ...) time_t now; gchar tbuf[21]; gint fd = -1; - struct client_thread_s *cn; - gchar *name = ""; + gchar *name; gchar buf[255]; + pth_t tid = pth_self(); + pth_attr_t attr; if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt) return; @@ -233,17 +220,13 @@ void log_write(const gchar *fmt, ...) return; } - pthread_mutex_lock(&cn_mutex); - cn = find_cn(pthread_self()); + attr = pth_attr_of(tid); - if (cn) { - if (!cn->name) - name = print_fmt(buf, sizeof(buf), "%i: ", cn->fd); - else - name = print_fmt(buf, sizeof(buf), "%s(%i): ", cn->name, cn->fd); - } + if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE) + name = "unknown"; - pthread_mutex_unlock(&cn_mutex); + pth_attr_destroy(attr); + name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid); if (!cmdline && log_syslog == TRUE) syslog(LOG_INFO, "%s%s", name, args); @@ -309,7 +292,8 @@ static int gcry_SecureCheck(const void *ptr) static void setup_gcrypt() { - gcry_check_version(NULL); + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + gcry_check_version(GCRYPT_VERSION); gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc, xfree); @@ -416,53 +400,36 @@ void cleanup_crypto(struct client_crypto_s **c) if (cr->outbuf) gcry_free(cr->outbuf); - pthread_cleanup_push(cleanup_crypto_handler, c); - pthread_testcancel(); - pthread_cleanup_pop(1); + cleanup_crypto_handler(c); } /* * This is called after a child_thread terminates. Set with - * pthread_cleanup_push(). + * pth_cleanup_push(). */ static void cleanup_cb(void *arg) { struct client_thread_s *cn = arg; struct client_s *cl = cn->cl; - cn->quit = TRUE; - log_write(N_("exiting, fd=%i"), cn->fd); - - if (cl->thd && (cl->thd->msg_fd[0] || cl->thd->msg_fd[1])) { - pthread_cancel(cn->msg_tid); - pthread_cancel(cn->msg_sender_tid); - pthread_join(cn->msg_sender_tid, NULL); - pthread_cond_destroy(&cn->msg_cond); - close(cl->thd->msg_fd[0]); - close(cl->thd->msg_fd[1]); - } - - pthread_join(cn->tid, NULL); MUTEX_LOCK(&cn_mutex); cn_thread_list = g_slist_remove(cn_thread_list, cn); MUTEX_UNLOCK(&cn_mutex); - if (pthread_mutex_trylock(&cn->msg_sender_mutex) == EBUSY) { - MUTEX_UNLOCK(&cn->msg_sender_mutex); + if (cn->msg_tid) { + pth_cancel(cn->msg_tid); + fprintf(stderr, "%s(%i): %s\n", __FILE__, __LINE__, __FUNCTION__); + pth_join(cn->msg_tid, NULL); + fprintf(stderr, "%s(%i): %s\n", __FILE__, __LINE__, __FUNCTION__); } - else - pthread_mutex_unlock(&cn->msg_sender_mutex); - - pthread_mutex_destroy(&cn->msg_sender_mutex); - pthread_cond_destroy(&cn->msg_sender_cond); for (;;) { - struct status_msg_s *m = g_slist_nth_data(cn->msg_queue, 0); + struct status_msg_s *m = g_slist_nth_data(cn->msg_list, 0); if (!m) break; - cn->msg_queue = g_slist_remove(cn->msg_queue, m); + cn->msg_list = g_slist_remove(cn->msg_list, m); g_free(m); } @@ -494,11 +461,8 @@ static void cleanup_cb(void *arg) cleanup_crypto(&cl->crypto); g_free(cl); - - if (cn->name) - g_free(cn->name); - g_free(cn); + log_write(N_("exiting, fd=%i"), cn->fd); send_status_all(STATUS_CLIENTS); } @@ -511,7 +475,10 @@ static void *client_thread(void *data) struct client_thread_s *thd = data; struct client_s *cl = g_malloc0(sizeof(struct client_s)); gpg_error_t rc; - pthread_attr_t attr; + pth_attr_t attr = pth_attr_of(pth_self()); + + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); /* * Prevent a race condition with init_new_connection() if this thread @@ -520,7 +487,7 @@ static void *client_thread(void *data) */ MUTEX_LOCK(&cn_mutex); MUTEX_UNLOCK(&cn_mutex); - pthread_cleanup_push(cleanup_cb, thd); + pth_cleanup_push(cleanup_cb, thd); if (!cl) { log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); @@ -545,7 +512,7 @@ static void *client_thread(void *data) goto fail; } - pthread_testcancel(); + pth_cancel_point(); } #endif @@ -558,7 +525,6 @@ static void *client_thread(void *data) cl->pinentry = pinentry_init(); if (!cl->pinentry) { - g_free(cl); log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); goto fail; } @@ -581,24 +547,12 @@ static void *client_thread(void *data) } #endif - if (pipe(thd->msg_fd) == -1) { - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno)); - goto fail; - } - - pthread_attr_init(&attr); - pthread_cond_init(&thd->msg_sender_cond, NULL); - pthread_mutex_init(&thd->msg_sender_mutex, NULL); - MUTEX_LOCK(&thd->msg_sender_mutex); - pthread_create(&thd->msg_sender_tid, &attr, client_msg_sender_thread, thd); - pthread_attr_destroy(&attr); - - pthread_cond_init(&thd->msg_cond, NULL); - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thd->msg_tid, &attr, client_msg_thread, thd); - pthread_attr_destroy(&attr); - + pth_mutex_init(&thd->msg_list_mutex); + attr = pth_attr_new(); + pth_attr_init(attr); + thd->msg_tid = pth_spawn(attr, client_msg_thread, thd); + pth_attr_destroy(attr); + pth_yield(thd->msg_tid); rc = send_status(cl->ctx, STATUS_CACHE, NULL); if (rc) { @@ -610,29 +564,28 @@ static void *client_thread(void *data) xmlSetStructuredErrorFunc(cl, xml_error_cb); for (;;) { - fd_set rfds; - int n; +#ifdef WITH_PINENTRY + pth_event_t pev = NULL; +#endif + pth_event_t ev; + pth_status_t st; - FD_ZERO(&rfds); - FD_SET(cl->thd->fd, &rfds); + ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->thd->fd); #ifdef WITH_PINENTRY - if (cl->pinentry->status == PINENTRY_RUNNING) - FD_SET(cl->pinentry->fd, &rfds); - - n = cl->thd->fd > cl->pinentry->fd ? cl->thd->fd : cl->pinentry->fd; -#else - n = cl->thd->fd; + if (cl->pinentry->status == PINENTRY_RUNNING) { + pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd); + ev = pth_event_concat(ev, pev, NULL); + } #endif - n = select(n+1, &rfds, NULL, NULL, NULL); - pthread_testcancel(); - if (n <= 0) - continue; + pth_wait(ev); + pth_event_isolate(ev); + st = pth_event_status(ev); - if (FD_ISSET(cl->thd->fd, &rfds)) { + if (st == PTH_STATUS_OCCURRED) { rc = assuan_process_next(cl->ctx); - pthread_testcancel(); + pth_cancel_point(); if (rc) { cl->inquire_status = INQUIRE_INIT; @@ -660,16 +613,24 @@ static void *client_thread(void *data) break; case INQUIRE_DONE: cl->inquire_status = INQUIRE_INIT; - pthread_testcancel(); rc = assuan_process_done(cl->ctx, 0); + pth_cancel_point(); break; } } } + pth_event_free(ev, PTH_FREE_THIS); + #ifdef WITH_PINENTRY + if (pev) { + pth_event_isolate(pev); + st = pth_event_status(pev); + pth_event_free(pev, PTH_FREE_THIS); + } + pinentry_iterate(cl, - cl->pinentry->fd != -1 && FD_ISSET(cl->pinentry->fd, &rfds)); + pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED); #endif } @@ -679,9 +640,8 @@ static void *client_thread(void *data) */ done: fail: - if (1) {} // Fixes compile time error with pthread_cleanup_push(). - pthread_cleanup_pop(1); - pthread_exit(PTHREAD_CANCELED); + pth_cleanup_pop(1); + pth_exit(PTH_CANCELED); return NULL; } @@ -1160,7 +1120,7 @@ static gboolean xml_import(const gchar *filename, const gchar *outfile, goto fail; } - if (read(fd, xmlbuf, st.st_size) == -1) { + if (pth_read(fd, xmlbuf, st.st_size) == -1) { rc = errno; close(fd); errno = rc; @@ -1443,10 +1403,8 @@ try_decrypt: static void init_new_connection(gint fd, gchar *addr) { - pthread_t tid; - pthread_attr_t attr; + pth_attr_t attr; struct client_thread_s *new; - int n; new = g_malloc0(sizeof(struct client_thread_s)); @@ -1464,27 +1422,28 @@ static void init_new_connection(gint fd, gchar *addr) new->remote = TRUE; #endif - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - n = pthread_create(&tid, &attr, client_thread, new); - pthread_attr_destroy(&attr); + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + new->tid = pth_spawn(attr, client_thread, new); + pth_attr_destroy(attr); - if (n) { + if (!new->tid) { g_free(new); close(fd); - log_write("pthread_create(): %s", strerror(n)); + log_write("pth_spawn() failed"); MUTEX_UNLOCK(&cn_mutex); return; } - new->tid = tid; cn_thread_list = g_slist_append(cn_thread_list, new); MUTEX_UNLOCK(&cn_mutex); if (addr) - log_write(N_("new connection: fd=%i, addr=%s"), fd, addr); + log_write(N_("new connection: tid=%p, fd=%i, addr=%s"), new->tid, fd, + addr); else - log_write(N_("new connection: fd=%i"), fd); + log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd); } #ifdef WITH_GNUTLS @@ -1500,6 +1459,10 @@ static void *get_in_addr(struct sockaddr *sa) static void *tcp_accept_thread(void *arg) { gint sockfd = (gint)arg; + pth_attr_t attr = pth_attr_of(pth_self()); + + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); for (;;) { struct sockaddr_storage raddr; @@ -1508,8 +1471,8 @@ static void *tcp_accept_thread(void *arg) gulong n; gchar *t; - fd = accept(sockfd, (struct sockaddr *)&raddr, &slen); - pthread_testcancel(); + fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen); + pth_cancel_point(); if (fd == -1) { if (errno != EAGAIN) { @@ -1540,12 +1503,12 @@ static void *tcp_accept_thread(void *arg) if (n < 0) n = 0; - usleep(n*100000); + pth_usleep(n*100000); } /* Just in case accept() failed for some reason other than EBADF */ quit = 1; - pthread_exit(PTHREAD_CANCELED); + pth_exit(PTH_CANCELED); return NULL; } #endif @@ -1553,14 +1516,18 @@ static void *tcp_accept_thread(void *arg) static void *accept_thread(void *arg) { gint sockfd = (gint)arg; + pth_attr_t attr = pth_attr_of(pth_self()); + + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); for (;;) { socklen_t slen = sizeof(struct sockaddr_un); struct sockaddr_un raddr; gint fd = -1; - fd = accept(sockfd, (struct sockaddr *)&raddr, &slen); - pthread_testcancel(); + fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen); + pth_cancel_point(); if (fd == -1) { if (errno != EAGAIN) { @@ -1579,15 +1546,20 @@ static void *accept_thread(void *arg) /* Just in case accept() failed for some reason other than EBADF */ quit = 1; - pthread_exit(PTHREAD_CANCELED); + pth_exit(PTH_CANCELED); return NULL; } static void *adjust_cache_timer_thread(void *arg) { + pth_attr_t attr = pth_attr_of(pth_self()); + + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); + for (;;) { - sleep(1); - pthread_testcancel(); + pth_sleep(1); + pth_cancel_point(); CACHE_LOCK(NULL); cache_adjust_timer(); CACHE_UNLOCK; @@ -1596,29 +1568,37 @@ static void *adjust_cache_timer_thread(void *arg) return NULL; } +static void keepalive_cleanup(void *arg) +{ + pth_event_t ev = arg; + + pth_event_free(ev, PTH_FREE_ALL); +} + static void *keepalive_thread(void *arg) { struct timespec ts; gint to = (gint)arg; - pthread_mutex_t m; - pthread_cond_t cond; + pth_mutex_t m; + pth_cond_t cond; + pth_attr_t attr = pth_attr_of(pth_self()); - pthread_cond_init(&cond, NULL); - pthread_mutex_init(&m, NULL); - pthread_mutex_lock(&m); + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); + pth_cond_init(&cond); + pth_mutex_init(&m); + pth_mutex_acquire(&m, FALSE, NULL); for (;;) { - pthread_cleanup_push(pthread_mutex_destroy, &m); - pthread_cleanup_push(pthread_cond_destroy, &cond); - pthread_cleanup_push(pthread_mutex_unlock, &m); + pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0)); + pth_cleanup_push(pth_mutex_release, (void *)&m); + pth_cleanup_push(keepalive_cleanup, ev); clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += to; - pthread_cond_timedwait(&cond, &m, &ts); - pthread_testcancel(); + pth_cond_await(&cond, &m, ev); + pth_cancel_point(); send_status_all(STATUS_KEEPALIVE); - pthread_cleanup_pop(0); - pthread_cleanup_pop(0); - pthread_cleanup_pop(0); + pth_cleanup_pop(1); + pth_cleanup_pop(0); } return NULL; @@ -1626,11 +1606,10 @@ static void *keepalive_thread(void *arg) static void startStopKeepAlive(gboolean term) { - pthread_attr_t attr; gint n = get_key_file_integer("global", "keepalive"); if (keepalive_tid) - pthread_cancel(keepalive_tid); + pth_cancel(keepalive_tid); keepalive_tid = 0; @@ -1638,22 +1617,23 @@ static void startStopKeepAlive(gboolean term) return; if (n > 0) { - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&keepalive_tid, &attr, keepalive_thread, (void *)n); - pthread_attr_destroy(&attr); + pth_attr_t attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + keepalive_tid = pth_spawn(attr, keepalive_thread, (void *)n); + pth_yield(keepalive_tid); + pth_attr_destroy(attr); } } static void server_loop(gint sockfd, gchar **socketpath) { - pthread_t accept_tid; + pth_t accept_tid; guint n; sigset_t sigset; gint n_clients = 0; - pthread_attr_t attr; - pthread_t cache_timeout_tid; - pthread_mutexattr_t mattr; + pth_attr_t attr; + pth_t cache_timeout_tid; sigemptyset(&sigset); @@ -1676,23 +1656,21 @@ static void server_loop(gint sockfd, gchar **socketpath) signal(SIGPIPE, SIG_IGN); sigprocmask(SIG_BLOCK, &sigset, NULL); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - pthread_mutexattr_init(&mattr); - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&cn_mutex, &mattr); - pthread_mutexattr_destroy(&mattr); log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name()); - pthread_attr_init(&attr); - pthread_create(&accept_tid, &attr, accept_thread, (void *)sockfd); + attr = pth_attr_new(); + pth_attr_init(attr); + accept_tid = pth_spawn(attr, accept_thread, (void *)sockfd); + pth_yield(accept_tid); startStopKeepAlive(FALSE); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&cache_timeout_tid, &attr, adjust_cache_timer_thread, NULL); - pthread_attr_destroy(&attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL); + pth_yield(cache_timeout_tid); + pth_attr_destroy(attr); do { gint sig; - sigwait(&sigset, &sig); + pth_sigwait(&sigset, &sig); log_write(N_("caught signal %i (%s)"), sig, strsignal(sig)); /* Caught a signal. */ @@ -1727,8 +1705,8 @@ static void server_loop(gint sockfd, gchar **socketpath) */ shutdown(sockfd, SHUT_RDWR); close(sockfd); - pthread_cancel(accept_tid); - pthread_join(accept_tid, NULL); + pth_cancel(accept_tid); + pth_join(accept_tid, NULL); #ifdef WITH_GNUTLS startStopTcp(TRUE); #endif @@ -1748,14 +1726,14 @@ static void server_loop(gint sockfd, gchar **socketpath) n_clients = n; } - sleep(1); + pth_sleep(1); MUTEX_LOCK(&cn_mutex); n = g_slist_length(cn_thread_list); MUTEX_UNLOCK(&cn_mutex); } startStopKeepAlive(TRUE); - pthread_cancel(cache_timeout_tid); + pth_cancel(cache_timeout_tid); cache_free(); } @@ -1880,14 +1858,13 @@ static gboolean startStopTcp(gboolean term) { struct addrinfo hints, *servinfo, *p; gint port = get_key_file_integer("global", "tcp_port"); - char buf[7]; - int n; - pthread_attr_t attr; + gchar buf[7]; + gint n; if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) { if (tcpSockFd != -1) { - pthread_cancel(tcpAcceptTid); - pthread_join(tcpAcceptTid, NULL); + pth_cancel(tcpAcceptTid); + pth_join(tcpAcceptTid, NULL); shutdown(tcpSockFd, SHUT_RDWR); close(tcpSockFd); tcpSockFd = -1; @@ -1968,9 +1945,8 @@ static gboolean startStopTcp(gboolean term) goto fail; } - pthread_attr_init(&attr); - pthread_create(&tcpAcceptTid, &attr, tcp_accept_thread, (void *)tcpSockFd); - pthread_attr_destroy(&attr); + tcpAcceptTid = pth_spawn(NULL, tcp_accept_thread, (void *)tcpSockFd); + pth_yield(tcpAcceptTid); return TRUE; fail: @@ -2010,7 +1986,6 @@ int main(int argc, char *argv[]) guint ptotal = 0; gint background = 1; gchar *convert = NULL; - pthread_mutexattr_t mattr; #ifdef WITH_PINENTRY gboolean disable_pinentry = FALSE; #endif @@ -2039,14 +2014,13 @@ int main(int argc, char *argv[]) #ifndef MEM_DEBUG xmem_init(); #endif + setup_gcrypt(); gpg_err_init(); assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT); g_mem_set_vtable(&mtable); assuan_set_malloc_hooks(xmalloc, xrealloc, xfree); xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup); xmlInitMemory(); - gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); - gcry_check_version(GCRYPT_VERSION); #ifdef WITH_GNUTLS gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck, xrealloc, xfree); @@ -2143,10 +2117,12 @@ int main(int argc, char *argv[]) } } - pthread_mutexattr_init(&mattr); - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&rcfile_mutex, &mattr); - pthread_mutexattr_destroy(&mattr); + pth_mutex_init(&cn_mutex); + pth_mutex_init(&cache_mutex); + pth_mutex_init(&rcfile_mutex); +#ifdef WITH_PINENTRY + pth_mutex_init(&pin_mutex); +#endif if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL) exit(EXIT_FAILURE); @@ -2179,8 +2155,6 @@ int main(int argc, char *argv[]) } #endif - setup_gcrypt(); - if (convert) { if (!outfile) usage(argv[0]); @@ -2345,13 +2319,6 @@ int main(int argc, char *argv[]) } g_free(datadir); - pthread_mutexattr_init(&mattr); - pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&cache_mutex, &mattr); - pthread_mutexattr_destroy(&mattr); -#ifdef WITH_PINENTRY - pthread_mutex_init(&pin_mutex, NULL); -#endif if (listen(sockfd, 0) == -1) { log_write("listen(): %s", strerror(errno)); @@ -2406,8 +2373,5 @@ do_exit: #if defined(DEBUG) && !defined(MEM_DEBUG) xdump(); #endif -#ifndef MEM_DEBUG - xmem_deinit(); -#endif exit(estatus); } diff --git a/src/pwmd.h b/src/pwmd.h index 06784b4d..e0fc11cc 100644 --- a/src/pwmd.h +++ b/src/pwmd.h @@ -26,10 +26,10 @@ static gboolean disable_mlock; static gchar *logfile; static gint quit; static gboolean cmdline; -static pthread_t keepalive_tid; +static pth_t keepalive_tid; #ifdef WITH_GNUTLS static int tcpSockFd; -pthread_t tcpAcceptTid; +pth_t tcpAcceptTid; static gboolean startStopTcp(gboolean term); #endif diff --git a/src/status.c b/src/status.c index 8048f4cd..c95c5426 100644 --- a/src/status.c +++ b/src/status.c @@ -27,30 +27,35 @@ struct status_thread_s { assuan_context_t ctx; gchar *status; const gchar *line; - pthread_t tid; + pth_t tid; gint fd[2]; + pth_event_t ev; }; static void cleanup(void *arg) { struct status_thread_s *s = arg; + if (s->tid) + pth_cancel(s->tid); + close(s->fd[0]); close(s->fd[1]); + pth_event_free(s->ev, PTH_FREE_ALL); g_free(s); } -static void *send_status_thread(void *arg) +static void *write_status_thread(void *arg) { struct status_thread_s *s = arg; gpg_error_t rc; - - pthread_cleanup_push(cleanup, s); - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pth_attr_t attr = pth_attr_of(pth_self()); + + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); + pth_cancel_state(PTH_CANCEL_ASYNCHRONOUS, NULL); rc = assuan_write_status(s->ctx, s->status, s->line); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - write(s->fd[1], &rc, sizeof(gpg_error_t)); - pthread_cleanup_pop(0); + pth_write(s->fd[1], &rc, sizeof(gpg_error_t)); return NULL; } @@ -65,10 +70,10 @@ gpg_error_t send_status(assuan_context_t ctx, status_msg_t which, gint n; gpg_error_t rc; struct status_thread_s *s; - struct timeval tv = {0, 0}; gint to = get_key_file_integer("global", "keepalive"); - fd_set rfds; - pthread_attr_t attr; + pth_attr_t attr; + pth_event_t tev; + pth_status_t st; if (fmt) { va_start(ap, fmt); @@ -130,130 +135,110 @@ gpg_error_t send_status(assuan_context_t ctx, status_msg_t which, s->status = status; s->line = line; - /* Since we use the keepalive from the configuration, it may be 0. If so, - * status messages would fail and abort the connection. So use a default - * that doesn't affect the configured keepalive value. */ - tv.tv_sec = to <= 0 ? DEFAULT_KEEPALIVE_TO : to; - if (pipe(s->fd) == -1) { n = errno; g_free(s); return gpg_error_from_errno(n); } - pthread_cleanup_push(cleanup, s); - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&s->tid, &attr, send_status_thread, s); - pthread_attr_destroy(&attr); - FD_ZERO(&rfds); - FD_SET(s->fd[0], &rfds); - n = s->fd[0] > s->fd[1] ? s->fd[0] : s->fd[1]; - n = select(n+1, &rfds, NULL, NULL, &tv); - - if (n <= 0) { - n = errno; - pthread_cancel(s->tid); + pth_cleanup_push(cleanup, s); + /* Since we use the keepalive from the configuration, it may be 0. If so, + * status messages would fail and abort the connection. So use a default + * that doesn't affect the configured keepalive value. */ + to = to <= 0 ? DEFAULT_KEEPALIVE_TO : to; + s->ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, s->fd[0]); + tev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0)); + s->ev = pth_event_concat(s->ev, tev, NULL); + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + s->tid = pth_spawn(attr, write_status_thread, s); + pth_yield(s->tid); + pth_attr_destroy(attr); + pth_wait(s->ev); + st = pth_event_status(s->ev); + + if (st == PTH_STATUS_FAILED) { + pth_cancel(s->tid); + s->tid = NULL; + rc = GPG_ERR_ASS_WRITE_ERROR; + } + else if (st == PTH_STATUS_OCCURRED) { + size_t len = pth_read(s->fd[0], &rc, sizeof(gpg_error_t)); - if (n) { - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(n)); - rc = gpg_error_from_errno(n); - } - else + if (len != sizeof(gpg_error_t)) { + log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno)); rc = GPG_ERR_ASS_WRITE_ERROR; + } - return rc; + s->tid = NULL; } + else { + st = pth_event_status(tev); - if (FD_ISSET(s->fd[0], &rfds)) { - size_t len = read(s->fd[0], &rc, sizeof(gpg_error_t)); - - if (len != sizeof(gpg_error_t)) { - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno)); + if (st == PTH_STATUS_OCCURRED) { + pth_cancel(s->tid); + s->tid = NULL; rc = GPG_ERR_ASS_WRITE_ERROR; } } - else - rc = GPG_ERR_ASS_WRITE_ERROR; - pthread_cleanup_pop(1); + pth_cleanup_pop(1); return rc; } -/* This is needed for FreeBSD systems (and maybe others). I'm guessing here, - * but I think it lets the scheduler let other threads do their work. If we - * were to do the write() in send_status_all() then write() would return - * before the signal was actually sent to client_msg_thread(). This is only - * called from send_status_all(). - */ -static void *write_status_msg(void *arg) +static void *do_send_status(void *arg) { - struct client_thread_s *cn =arg; - size_t len; - - pthread_cond_signal(&cn->msg_cond); - len = write(cn->msg_fd[1], &cn->msg, sizeof(status_msg_t)); - - if (len != sizeof(status_msg_t)) - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno)); + struct client_s *cl = arg; + gpg_error_t rc; + rc = send_status(cl->ctx, cl->msg, NULL); + pth_exit((void *)rc); return NULL; } -void send_status_all(status_msg_t which) -{ - guint i, t; - - MUTEX_LOCK(&cn_mutex); - - for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) { - struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i); - pthread_t tid; - - if (cn->quit) - continue; - - cn->msg = which; - pthread_create(&tid, NULL, write_status_msg, cn); - pthread_join(tid, NULL); - } - - MUTEX_UNLOCK(&cn_mutex); -} - -/* The msg_sender_mutex should have been locked before calling this thread - * entry point. */ -void *client_msg_sender_thread(void *arg) +void *client_msg_thread(void *arg) { struct client_thread_s *thd = arg; + pth_mutex_t m; + pth_attr_t attr = pth_attr_of(pth_self()); - for (;;) { - struct status_msg_s *msg; - gpg_error_t rc; + pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__); + pth_attr_destroy(attr); + pth_mutex_init(&m); + pth_cond_init(&thd->msg_cond); + pth_mutex_acquire(&m, FALSE, NULL); - pthread_cond_wait(&thd->msg_sender_cond, &thd->msg_sender_mutex); - pthread_testcancel(); + for (;;) { + pth_cond_await(&thd->msg_cond, &m, NULL); + pth_cancel_point(); - /* The messages may have been stacked while waiting for send_status() - * to return. Send what's in the queue. */ for (;;) { - msg = g_slist_nth_data(thd->msg_queue, 0); + status_msg_t *msg; + pth_t tid; + gpg_error_t rc; + + MUTEX_LOCK(&thd->msg_list_mutex); + msg = g_slist_nth_data(thd->msg_list, 0); + if (msg) + thd->msg_list = g_slist_remove(thd->msg_list, msg); + + MUTEX_UNLOCK(&thd->msg_list_mutex); + if (!msg) break; - /* Unlock to prevent blocking in client_msg_thread(). */ - MUTEX_UNLOCK(&thd->msg_sender_mutex); - rc = send_status(thd->cl->ctx, msg->msg, NULL); - MUTEX_LOCK(&thd->msg_sender_mutex); - thd->msg_queue = g_slist_remove(thd->msg_queue, msg); + thd->cl->msg = *msg; g_free(msg); - pthread_testcancel(); + tid = pth_spawn(NULL, do_send_status, thd->cl); + pth_yield(tid); + pth_join(tid, (void **)&rc); + pth_cancel_point(); if (rc) { - log_write(N_("msg for %i failed: %s"), thd->fd, - pwmd_strerror(rc)); - pthread_cancel(thd->tid); + log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(rc)); + pth_cancel(thd->tid); break; } } @@ -262,76 +247,46 @@ void *client_msg_sender_thread(void *arg) return NULL; } -/* - * This function waits for a signal from send_status_all() then appends a - * message read from a pipe to the clients message queue. The actual sending - * of the message is done in client_msg_sender_thread() which waits for a - * signal from this function. This prevents blocking in assuan_send_status() - * when sending to remote clients. This also avoids duplicate status messages. - * If an existing status message in the message queue has the same type as the - * current message the the current one will be skipped. This avoids flooding - * the client with old status messages. - */ -void *client_msg_thread(void *arg) +static gboolean msg_list_dup(GSList *list, status_msg_t which) { - struct client_thread_s *thd = arg; - pthread_mutex_t mu; + guint i, t; - pthread_mutex_init(&mu, NULL); - pthread_mutex_lock(&mu); + for (t = g_slist_length(list), i = 0; i < t; i++) { + status_msg_t *m = g_slist_nth_data(list, i); - for (;;) { - fd_set rfds; - int n; - status_msg_t m; - size_t len; - struct status_msg_s *msg; - - pthread_cleanup_push(pthread_mutex_destroy, &mu); - pthread_cleanup_push(pthread_mutex_unlock, &mu); - pthread_cond_wait(&thd->msg_cond, &mu); - pthread_testcancel(); - FD_ZERO(&rfds); - FD_SET(thd->msg_fd[0], &rfds); - n = select(thd->msg_fd[0]+1, &rfds, NULL, NULL, NULL); - pthread_testcancel(); - - if (n <= 0 || !FD_ISSET(thd->msg_fd[0], &rfds)) - continue; + if (*m == which) + return TRUE; + } - len = read(thd->msg_fd[0], &m, sizeof(status_msg_t)); - pthread_testcancel(); + return FALSE; +} - if (len != sizeof(status_msg_t)) { - log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno)); - continue; - } +void send_status_all(status_msg_t which) +{ + guint i, t; - MUTEX_LOCK(&thd->msg_sender_mutex); + MUTEX_LOCK(&cn_mutex); - for (n = 0; n < g_slist_length(thd->msg_queue); n++) { - msg = g_slist_nth_data(thd->msg_queue, n); + for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) { + struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i); + status_msg_t *m; - if (msg->msg == m) - goto done; - } + if (msg_list_dup(cn->msg_list, which)) + continue; - msg = g_malloc(sizeof(struct status_msg_s)); + m = g_malloc(sizeof(status_msg_t)); - if (!msg) { + if (!m) { log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM)); - MUTEX_UNLOCK(&thd->msg_sender_mutex); continue; } - msg->msg = m; - thd->msg_queue = g_slist_append(thd->msg_queue, msg); -done: - MUTEX_UNLOCK(&thd->msg_sender_mutex); - pthread_cond_signal(&thd->msg_sender_cond); - pthread_cleanup_pop(0); - pthread_cleanup_pop(0); + *m = which; + MUTEX_LOCK(&cn->msg_list_mutex); + cn->msg_list = g_slist_append(cn->msg_list, m); + MUTEX_UNLOCK(&cn->msg_list_mutex); + pth_cond_notify(&cn->msg_cond, FALSE); } - return NULL; + MUTEX_UNLOCK(&cn_mutex); } diff --git a/src/tls.c b/src/tls.c index 76a8e044..fbde65d9 100644 --- a/src/tls.c +++ b/src/tls.c @@ -176,7 +176,7 @@ int read_hook(assuan_context_t ctx, assuan_fd_t fd, void *data, struct client_s *cl = assuan_get_pointer(ctx); if (!cl || !cl->thd->remote) - *ret = read((int)fd, data, len); + *ret = pth_read((int)fd, data, len); else { do { *ret = gnutls_record_recv(cl->thd->tls->ses, data, len); @@ -218,7 +218,7 @@ int write_hook(assuan_context_t ctx, assuan_fd_t fd, const void *data, struct client_s *cl = assuan_get_pointer(ctx); if (!cl || !cl->thd->remote) - *ret = write((int)fd, data, len); + *ret = pth_write((int)fd, data, len); else { do { *ret = gnutls_record_send(cl->thd->tls->ses, data, len); -- 2.11.4.GIT