aboutsummaryrefslogtreecommitdiffstats
path: root/src/estream.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2026-04-30 13:38:11 +0200
committerWerner Koch <[email protected]>2026-04-30 13:38:11 +0200
commit50f0c56bdd36f7f709a62503942ac55399dafb9c (patch)
treed38aa72fa58a11e41fb95bafc2e2270e777a00ea /src/estream.c
parentFix possible stack overflow in es_printf for %.100f format. (diff)
downloadlibgpg-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.c25
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 ();
}