4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-22 15:07:43 +08:00
Sebastian Huber b0cb9f85ca Use global stdio streams for all configurations
The _REENT_GLOBAL_STDIO_STREAMS was introduced by commit
668a4c8722090fffd10869dbb15b879651c1370d in 2017.  Since then it was enabled by
default for RTEMS.  Recently, the option was enabled for Cygwin which
previously used an alternative implementation to use global stdio streams.

In Newlib, the stdio streams are defined to thread-specific pointers
_reent::_stdin, _reent::_stdout and _reent::_stderr.  If the option is disabled
(the default for most systems), then these pointers are initialized to
thread-specific FILE objects which use file descriptors 0, 1, and 2,
respectively.  There are at least three problems with this:

(1) The thread-specific FILE objects are closed by _reclaim_reent().  This
    leads to problems with language run-time libraries that provide wrappers to
    the C/POSIX stdio streams (for example C++ and Ada), since they use the
    thread-specific FILE objects of the initialization thread.  In case the
    initialization thread is deleted, then they use freed memory.

(2) Since thread-specific FILE objects are used with a common output device via
    file descriptors 0, 1 and 2, the locking at FILE object level cannot ensure
    atomicity of the output, e.g. a call to printf().

(3) There are resource managment issues, see:

    https://sourceware.org/pipermail/newlib/2022/019558.html

    https://bugs.linaro.org/show_bug.cgi?id=5841

This patch enables the _REENT_GLOBAL_STDIO_STREAMS behaviour for all Newlib
configurations and removes the option.  This removes a couple of #ifdef blocks.
2022-06-10 20:13:52 +02:00

100 lines
2.0 KiB
C

/*
FUNCTION
<<reent>>---definition of impure data.
INDEX
reent
DESCRIPTION
This module defines the impure data area used by the
non-reentrant functions, such as strtok.
*/
#include <stdlib.h>
#include <reent.h>
#ifdef _REENT_ONLY
#ifndef REENTRANT_SYSCALLS_PROVIDED
#define REENTRANT_SYSCALLS_PROVIDED
#endif
#endif
#ifndef REENTRANT_SYSCALLS_PROVIDED
/* We use the errno variable used by the system dependent layer. */
#undef errno
int errno;
#endif
void
_reclaim_reent (struct _reent *ptr)
{
if (ptr != _impure_ptr)
{
/* used by mprec routines. */
#ifdef _REENT_SMALL
if (ptr->_mp) /* don't bother allocating it! */
{
#endif
if (_REENT_MP_FREELIST(ptr))
{
int i;
for (i = 0; i < _Kmax; i++)
{
struct _Bigint *thisone, *nextone;
nextone = _REENT_MP_FREELIST(ptr)[i];
while (nextone)
{
thisone = nextone;
nextone = nextone->_next;
_free_r (ptr, thisone);
}
}
_free_r (ptr, _REENT_MP_FREELIST(ptr));
}
if (_REENT_MP_RESULT(ptr))
_free_r (ptr, _REENT_MP_RESULT(ptr));
#ifdef _REENT_SMALL
}
#endif
#ifdef _REENT_SMALL
if (ptr->_emergency)
_free_r (ptr, ptr->_emergency);
if (ptr->_mp)
_free_r (ptr, ptr->_mp);
if (ptr->_r48)
_free_r (ptr, ptr->_r48);
if (ptr->_localtime_buf)
_free_r (ptr, ptr->_localtime_buf);
if (ptr->_asctime_buf)
_free_r (ptr, ptr->_asctime_buf);
if (ptr->_signal_buf)
_free_r (ptr, ptr->_signal_buf);
if (ptr->_misc)
_free_r (ptr, ptr->_misc);
#endif
if (ptr->_cvtbuf)
_free_r (ptr, ptr->_cvtbuf);
/* We should free _sig_func to avoid a memory leak, but how to
do it safely considering that a signal may be delivered immediately
after the free?
if (ptr->_sig_func)
_free_r (ptr, ptr->_sig_func);*/
if (ptr->__cleanup)
{
/* cleanup won't reclaim memory 'coz usually it's run
before the program exits, and who wants to wait for that? */
ptr->__cleanup (ptr);
}
/* Malloc memory not reclaimed; no good way to return memory anyway. */
}
}