Re: [PATCH v2 08/11] Add stdio_exit_handler()

Takashi Yano <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
On Thu, 12 May 2022 14:11:40 +0200
Matthew Joyce wrote:
> From: Matt Joyce <[email protected]>
> 
> Added a dedicated stdio exit handler to avoid using _GLOBAL_REENT
> in exit().
> ---
>  newlib/libc/include/sys/reent.h |  2 ++
>  newlib/libc/stdio/findfp.c      | 11 ++++++++++-
>  newlib/libc/stdlib/exit.c       |  5 +++--
>  winsup/cygwin/signal.cc         |  5 +++--
>  4 files changed, 18 insertions(+), 5 deletions(-)
> 
> diff --git a/newlib/libc/include/sys/reent.h b/newlib/libc/include/sys/reent.h
> index 4b0d68610..067294dc7 100644
> --- a/newlib/libc/include/sys/reent.h
> +++ b/newlib/libc/include/sys/reent.h
> @@ -837,6 +837,8 @@ extern struct _reent *_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
>  
>  extern struct _reent _impure_data __ATTRIBUTE_IMPURE_DATA__;
>  
> +extern void (*__stdio_exit_handler) (void);
> +
>  void _reclaim_reent (struct _reent *);
>  
>  /* #define _REENT_ONLY define this to get only reentrant routines */
> diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c
> index 5b0402ac1..719886e27 100644
> --- a/newlib/libc/stdio/findfp.c
> +++ b/newlib/libc/stdio/findfp.c
> @@ -26,6 +26,8 @@
>  #include <sys/lock.h>
>  #include "local.h"
>  
> +void (*__stdio_exit_handler) (void);
> +
>  #if defined(_REENT_SMALL) && !defined(_REENT_GLOBAL_STDIO_STREAMS)
>  const struct __sFILE_fake __sf_fake_stdin =
>      {_NULL, 0, 0, 0, 0, {_NULL, 0}, 0, _NULL};
> @@ -153,6 +155,12 @@ sfmoreglue (struct _reent *d, int n)
>    return &g->glue;
>  }
>  
> +static void
> +stdio_exit_handler (void)
> +{
> +  (void) _fwalk_reent (_GLOBAL_REENT, CLEANUP_FILE);
> +}
> +
>  /*
>   * Find a free FILE for fopen et al.
>   */
> @@ -166,12 +174,13 @@ __sfp (struct _reent *d)
>  
>    _newlib_sfp_lock_start ();
>  
> -  if (_GLOBAL_REENT->__cleanup == NULL) {
> +  if (__stdio_exit_handler == NULL) {
>  #ifdef _REENT_GLOBAL_STDIO_STREAMS
>      _GLOBAL_REENT->__sglue._niobs = 3;
>      _GLOBAL_REENT->__sglue._iobs = &__sf[0];
>  #endif
>      __sinit (_GLOBAL_REENT);
> +    __stdio_exit_handler = stdio_exit_handler;
>    }
>  
>    for (g = &_GLOBAL_REENT->__sglue;; g = g->_next)
> diff --git a/newlib/libc/stdlib/exit.c b/newlib/libc/stdlib/exit.c
> index 3e618914e..9b7bd518b 100644
> --- a/newlib/libc/stdlib/exit.c
> +++ b/newlib/libc/stdlib/exit.c
> @@ -59,7 +59,8 @@ exit (int code)
>  #endif
>      __call_exitprocs (code, NULL);
>  
> -  if (_GLOBAL_REENT->__cleanup)
> -    (*_GLOBAL_REENT->__cleanup) (_GLOBAL_REENT);
> +  if (__stdio_exit_handler != NULL)
> +    (*__stdio_exit_handler) ();
> +
>    _exit (code);
>  }
> diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
> index 9b6c2509d..f5f2efdc7 100644
> --- a/winsup/cygwin/signal.cc
> +++ b/winsup/cygwin/signal.cc
> @@ -13,6 +13,7 @@ details. */
>  #include <stdlib.h>
>  #include <sys/cygwin.h>
>  #include <sys/signalfd.h>
> +#include <sys/reent.h> /* needed for __stdio_exit_handler declaration */
>  #include "pinfo.h"
>  #include "sigproc.h"
>  #include "cygtls.h"
> @@ -408,8 +409,8 @@ abort (void)
>    _my_tls.call_signal_handler (); /* Call any signal handler */
>  
>    /* Flush all streams as per SUSv2.  */
> -  if (_GLOBAL_REENT->__cleanup)
> -    _GLOBAL_REENT->__cleanup (_GLOBAL_REENT);
> +  if (__stdio_exit_handler != NULL)
> +    (*__stdio_exit_handler) ();
>    do_exit (SIGABRT);	/* signal handler didn't exit.  Goodbye. */
>  }
>  
> -- 
> 2.31.1
> 

After this commit, "ps | cat" outputs nothing in cygwin. However,
just "ps" and "ls | cat" works. "stdbuf -o 0 ps | cat" also works.

I am not sure this is the right thing, however, I found the following
patch solves the issue. It seems that initializing __stdio_exit_handler
is missing.

diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c
index 19952d4e0..e759b5402 100644
--- a/newlib/libc/stdio/findfp.c
+++ b/newlib/libc/stdio/findfp.c
@@ -63,6 +63,8 @@ struct _glue __sglue = {NULL, 3, &_GLOBAL_REENT->__sf[0]};
 #endif
 #endif
 
+static void stdio_exit_handler (void);
+
 #if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
 _NOINLINE_STATIC void
 #else
@@ -109,6 +111,11 @@ std (FILE *ptr,
   if (__stextmode (ptr->_file))
     ptr->_flags |= __SCLE;
 #endif
+
+  if (__stdio_exit_handler == NULL) {
+    __sinit (_GLOBAL_REENT);
+    __stdio_exit_handler = stdio_exit_handler;
+  }
 }
 
 static inline void

Could you please have a look?

-- 
Takashi Yano <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.