From 212a325d428e0ab5c51c42a3ea33efb21ad1f79f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 12 Jul 2013 17:26:55 +0900 Subject: [PATCH] gpg: signal handling fix * include/dotlock.h (dotlock_remove_lockfiles_reclaim): New. (dotlock_destroy, dotlock_remove_lockfiles): Add a flag to reclaim memory or not. * util/dotlock.c (dotlock_create): Use dotlock_remove_lockfiles_reclaim for atexit. (dotlock_destroy_unix, dotlock_destroy) (dotlock_remove_lockfiles): Add a reclaim flag. (dotlock_remove_lockfiles_reclaim): New. * g10/signal.c (got_fatal_signal): Disable flag of reclaim memory to avoid non-async-face call. * g10/keydb.c (maybe_create_keyring): Follow the API change. * g10/gpgv.c: Follow the API change. -- signal handler got_fatal_signal should not call non-async-signal-safe functions. When malloc is interrupted by a signal, it screws up. This issue is reported: https://bugs.g10code.com/gnupg/issue1515 http://bugs.debian.org/399904 --- g10/gpgv.c | 4 ++-- g10/keydb.c | 2 +- g10/signal.c | 2 +- include/dotlock.h | 5 +++-- util/dotlock.c | 36 +++++++++++++++++++++++++----------- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/g10/gpgv.c b/g10/gpgv.c index 9ee80321e..2d51829fd 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -434,7 +434,7 @@ void rl_free_line_state (void) {} void dotlock_disable(void) {} dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags) { return NULL; } -void dotlock_destroy (dotlock_t h) {} +void dotlock_destroy (dotlock_t h, int reclaim) {} int dotlock_take (dotlock_t h, long timeout) { return 0;} int dotlock_release (dotlock_t h) {return 0;} -void dotlock_remove_lockfiles (void) {} +void dotlock_remove_lockfiles (void, int reclaim) {} diff --git a/g10/keydb.c b/g10/keydb.c index d6d83e252..8be194520 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -181,7 +181,7 @@ maybe_create_keyring (char *filename, int force) if (lockhd) { dotlock_release (lockhd); - dotlock_destroy (lockhd); + dotlock_destroy (lockhd, 1); } return rc; } diff --git a/g10/signal.c b/g10/signal.c index 086bf51d3..44b863d1c 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -122,7 +122,7 @@ got_fatal_signal( int sig ) /* Reset action to default action and raise signal again. */ init_one_signal (sig, SIG_DFL, 0); - dotlock_remove_lockfiles (); + dotlock_remove_lockfiles (0); #ifdef __riscos__ riscos_close_fds (); #endif /* __riscos__ */ diff --git a/include/dotlock.h b/include/dotlock.h index 920a81a16..04537929d 100644 --- a/include/dotlock.h +++ b/include/dotlock.h @@ -101,10 +101,11 @@ void dotlock_disable (void); dotlock_t dotlock_create (const char *file_to_lock, unsigned int flags); void dotlock_set_fd (dotlock_t h, int fd); int dotlock_get_fd (dotlock_t h); -void dotlock_destroy (dotlock_t h); +void dotlock_destroy (dotlock_t h, int reclaim); int dotlock_take (dotlock_t h, long timeout); int dotlock_release (dotlock_t h); -void dotlock_remove_lockfiles (void); +void dotlock_remove_lockfiles (int reclaim); +void dotlock_remove_lockfiles_reclaim (void); #ifdef __cplusplus } diff --git a/util/dotlock.c b/util/dotlock.c index c5f3a784b..27c2bb23d 100644 --- a/util/dotlock.c +++ b/util/dotlock.c @@ -128,7 +128,7 @@ unlinked using the atexit handler. If you don't need the lock file anymore, you may also explicitly remove it with a call to: - dotlock_destroy (h); + dotlock_destroy (h, 1); To actually lock the file, you use: @@ -823,7 +823,7 @@ dotlock_create (const char *file_to_lock, unsigned int flags) if ( !initialized ) { - atexit (dotlock_remove_lockfiles); + atexit (dotlock_remove_lockfiles_reclaim); initialized = 1; } @@ -881,13 +881,14 @@ dotlock_get_fd (dotlock_t h) #ifdef HAVE_POSIX_SYSTEM /* Unix specific code of destroy_dotlock. */ static void -dotlock_destroy_unix (dotlock_t h) +dotlock_destroy_unix (dotlock_t h, int reclaim) { if (h->locked && h->lockname) unlink (h->lockname); if (h->tname && !h->use_o_excl) unlink (h->tname); - jnlib_free (h->tname); + if (reclaim) + jnlib_free (h->tname); } #endif /*HAVE_POSIX_SYSTEM*/ @@ -911,7 +912,7 @@ dotlock_destroy_w32 (dotlock_t h) /* Destroy the locck handle H and release the lock. */ void -dotlock_destroy (dotlock_t h) +dotlock_destroy (dotlock_t h, int reclaim) { dotlock_t hprev, htmp; @@ -938,11 +939,13 @@ dotlock_destroy (dotlock_t h) #ifdef HAVE_DOSISH_SYSTEM dotlock_destroy_w32 (h); #else /* !HAVE_DOSISH_SYSTEM */ - dotlock_destroy_unix (h); + dotlock_destroy_unix (h, reclaim); #endif /* HAVE_DOSISH_SYSTEM */ - jnlib_free (h->lockname); + if (reclaim) + jnlib_free (h->lockname); } - jnlib_free(h); + if (reclaim) + jnlib_free (h); } @@ -1284,9 +1287,14 @@ dotlock_release (dotlock_t h) /* Remove all lockfiles. This is called by the atexit handler installed by this module but may also be called by other - termination handlers. */ + termination handlers. + + When RECLAIM == 0, it doesn't reclaim memory allocated. + This is useful calling by signal handlers. +*/ + void -dotlock_remove_lockfiles (void) +dotlock_remove_lockfiles (int reclaim) { dotlock_t h, h2; @@ -1301,7 +1309,13 @@ dotlock_remove_lockfiles (void) while ( h ) { h2 = h->next; - dotlock_destroy (h); + dotlock_destroy (h, reclaim); h = h2; } } + +void +dotlock_remove_lockfiles_reclaim (void) +{ + dotlock_remove_lockfiles (1); +}