[PATCH] Add comments to explain when a stream is freed by, __libc_freeres().

Carlos O'Donell carlos@redhat.com
Fri May 22 20:37:20 GMT 2020


In bug 26022 a user reports that valgrind shows two unfreed
allocations when using stderr.  This is normal, we don't free
unbuffered streams in __libc_freeres() because users expect
that such streams will be available all the way through the
process shutdown.

To suppress this I've filed the following valgrind issue:
https://bugs.kde.org/show_bug.cgi?id=421931
---
 libio/genops.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/libio/genops.c b/libio/genops.c
index 28419cc963..d533d47fd5 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -768,7 +768,7 @@ weak_alias (_IO_flush_all_linebuffered, _flushlbf)
    function sin the libc_freeres section.  Those are called as part of
    the atexit routine, just like _IO_cleanup.  The problem is we do
    not know whether the freeres code is called first or _IO_cleanup.
-   if the former is the case, we set the DEALLOC_BUFFER variable to
+   if the former is the case, we set the dealloc_buffers variable to
    true and _IO_unbuffer_all will take care of the rest.  If
    _IO_unbuffer_all is called first we add the streams to a list
    which the freeres function later can walk through.  */
@@ -796,8 +796,23 @@ _IO_unbuffer_all (void)
 	legacy = 1;
 #endif
 
+      /* We free a stream if:
+
+	 (1) The stream is buffered and was used (_mode != 0), and
+	     so the user can't expect any output to be printed during
+	     shutdown since absolute order of destructors is not
+	     explicitly guaranteed.
+
+	 (2) The stream is buffered and is a legacy stream used for
+	     backwards compatibility with legacy libstdc++
+	     implementations.
+
+	 By default stderr starts unbuffered and so by default we
+	 never process it here, and as such it is always available for
+	 late destructors to use, and will not be freed by the
+	 buffer_free function below (unless it is changed by the
+	 user).  */
       if (! (fp->_flags & _IO_UNBUFFERED)
-	  /* Iff stream is un-orientated, it wasn't used. */
 	  && (legacy || fp->_mode != 0))
 	{
 #ifdef _IO_MTSAFE_IO
@@ -844,11 +859,13 @@ _IO_unbuffer_all (void)
 #endif
 }
 
-
+/* Called by __libc_freeres() to free streams.  */
 libc_freeres_fn (buffer_free)
 {
   dealloc_buffers = true;
 
+  /* See the note in _IO_unbuffer_all about when a stream is
+     considered for freeing.  */
   while (freeres_list != NULL)
     {
       free (freeres_list->_freeres_buf);
-- 
2.26.2



More information about the Libc-alpha mailing list