diff options
| author | Werner Koch <[email protected]> | 2026-04-30 13:38:11 +0200 |
|---|---|---|
| committer | Werner Koch <[email protected]> | 2026-04-30 13:38:11 +0200 |
| commit | 50f0c56bdd36f7f709a62503942ac55399dafb9c (patch) | |
| tree | d38aa72fa58a11e41fb95bafc2e2270e777a00ea /src/estream.c | |
| parent | Fix possible stack overflow in es_printf for %.100f format. (diff) | |
| download | libgpg-error-50f0c56bdd36f7f709a62503942ac55399dafb9c.tar.gz libgpg-error-50f0c56bdd36f7f709a62503942ac55399dafb9c.zip | |
Fix possible lockup in an atexit handler
* src/estream.c (_gpgrt_fflush): Add arg in_atexit and skip the flush in
this mode if the lock can not be taken. Change all callers.
--
The problem should up with gpgsm encryption on the standard mode and a
no public key error. In this case the process got stuck in the atexit
handler after a FAILURE gpgsm-exit status line to stderr. It is
better not to have a hanging process than having flushed everything.
Diffstat (limited to 'src/estream.c')
| -rw-r--r-- | src/estream.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/src/estream.c b/src/estream.c index 4bf3bd3..55709f8 100644 --- a/src/estream.c +++ b/src/estream.c @@ -599,7 +599,7 @@ static void do_deinit (void) { /* Flush all streams. */ - _gpgrt_fflush (NULL); + _gpgrt_fflush (NULL, 1); /* 1 = we are in an atexit handler */ /* We should release the estream_list. However there is one problem: That list is also used to search for the standard @@ -4552,8 +4552,9 @@ do_fflush (estream_t stream) } +/* IN_ATEXIT is set when this function is called by an atexit handler. */ int -_gpgrt_fflush (estream_t stream) +_gpgrt_fflush (estream_t stream, int in_atexit) { int err; @@ -4572,9 +4573,23 @@ _gpgrt_fflush (estream_t stream) for (item = estream_list; item; item = item->next) if (item->stream) { - lock_stream (item->stream); - err |= do_fflush (item->stream); - unlock_stream (item->stream); + if (in_atexit) + { + /* Do not flush if we can't take the lock while we are + * in an atexit handler. The atexit handler might + * have been called while the stream was locked. */ + if (!trylock_stream (item->stream)) + { + err |= do_fflush (item->stream); + unlock_stream (item->stream); + } + } + else + { + lock_stream (item->stream); + err |= do_fflush (item->stream); + unlock_stream (item->stream); + } } unlock_list (); } |
