[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