Ticket #1246: PR#1246-newlib-1.15.0-rtems_stdio_cleanup.diff

File PR#1246-newlib-1.15.0-rtems_stdio_cleanup.diff, 4.6 KB (added by strauman, on 08/24/07 at 00:21:02)

fix newlibc's reclaim_reent() [rtems only] so it can be used to plug memory leak

Line 
1 - This patch addresses rtems PR#1246 (plug memory leak when thread is deleted)
2   the patch prevents the reent 'cleanup' function from performing I/O since
3   __reclaim_reent() is called at a point where the thread is already quite dead.
4   __reclaim_reent() should only reclaim memory and not do any I/O operations.
5
6 - Patch affects only RTEMS (by means of #ifdef)
7 - NOTE: companion patch 'rtems-newlibc-1.14.0-reclaim_reent.diff'
8         for RTEMS is necessary (cpukit/libcsupport/src/newlib.c)
9 - Patch assumes PR1247 patch was applied prior to this one (otherwise a minor
10   warning 'hunk offset' is printed).
11*** newlib-1.15.0/newlib/libc/include/sys/config.h.cleanstdio.diff.orig 2006-08-29 14:00:59.000000000 -0700
12--- newlib-1.15.0/newlib/libc/include/sys/config.h      2007-06-20 17:22:52.000000000 -0700
13***************
14*** 182,187 ****
15--- 182,188 ----
16  #if defined(__rtems__)
17  #define __FILENAME_MAX__ 255
18  #define _READ_WRITE_RETURN_TYPE _ssize_t
19+ #define _STDIO_CLEANUP_NO_IO_SYSCALLS
20  #endif
21 
22  #ifndef __IMPORT
23*** newlib-1.15.0/newlib/libc/stdio/fclose.c.cleanstdio.diff.orig       2006-12-14 14:47:12.000000000 -0800
24--- newlib-1.15.0/newlib/libc/stdio/fclose.c    2007-06-20 17:22:52.000000000 -0700
25***************
26*** 64,69 ****
27--- 64,89 ----
28  #include <sys/lock.h>
29  #include "local.h"
30 
31+ static void
32+ _DEFUN(_do_reclaim_fp, (rptr, fp, is_locked),
33+       struct _reent *rptr _AND
34+       register FILE * fp  _AND
35+         int            is_locked)
36+ {
37+   if (fp->_flags & __SMBF)
38+     _free_r (rptr, (char *) fp->_bf._base);
39+   if (HASUB (fp))
40+     FREEUB (fp);
41+   if (HASLB (fp))
42+     FREELB (fp);
43+   fp->_flags = 0;             /* release this FILE for reuse */
44+   if ( is_locked )
45+     _funlockfile (fp);
46+ #ifndef __SINGLE_THREAD__
47+   __lock_close_recursive (fp->_lock);
48+ #endif
49+ }
50+
51  int
52  _DEFUN(_fclose_r, (rptr, fp),
53        struct _reent *rptr _AND
54***************
55*** 92,114 ****
56    r = fflush (fp);
57    if (fp->_close != NULL && (*fp->_close) (fp->_cookie) < 0)
58      r = EOF;
59!   if (fp->_flags & __SMBF)
60!     _free_r (rptr, (char *) fp->_bf._base);
61!   if (HASUB (fp))
62!     FREEUB (fp);
63!   if (HASLB (fp))
64!     FREELB (fp);
65!   fp->_flags = 0;             /* release this FILE for reuse */
66!   _funlockfile (fp);
67! #ifndef __SINGLE_THREAD__
68!   __lock_close_recursive (fp->_lock);
69! #endif
70 
71    __sfp_lock_release ();
72 
73    return (r);
74  }
75 
76  #ifndef _REENT_ONLY
77 
78  int
79--- 112,145 ----
80    r = fflush (fp);
81    if (fp->_close != NULL && (*fp->_close) (fp->_cookie) < 0)
82      r = EOF;
83!   _do_reclaim_fp(rptr, fp, 1);
84 
85    __sfp_lock_release ();
86 
87    return (r);
88  }
89 
90+ int
91+ _DEFUN(__reclaim_fp, (fp),
92+       register FILE * fp)
93+ {
94+   /* must not lock anything; thread might be
95+    * halfway torn-down already.
96+    * ASSUME: 1) fp is part of thread-local reent; hence no need to __sfp_lock_acquire()
97+    *         2) no other thread is using fp anymore hence it is OK not to lock
98+    *         3) CHECK_INIT is not needed since the cleanup is only invoked
99+    *            if __sdidinit
100+    *
101+    * PS: it really doesn't make much sense to use internal locking on a FILE
102+    *     that is thread-local (stdin/stdout/stderr). Too bad we don't have
103+    *     an option...
104+    */
105+   if ( fp )
106+       _do_reclaim_fp( _REENT, fp, 0 /* we didn't lock fp */);
107+
108+   return (0);
109+ }
110+
111  #ifndef _REENT_ONLY
112 
113  int
114*** newlib-1.15.0/newlib/libc/stdio/findfp.c.cleanstdio.diff.orig       2007-06-20 17:21:24.000000000 -0700
115--- newlib-1.15.0/newlib/libc/stdio/findfp.c    2007-06-20 17:22:52.000000000 -0700
116***************
117*** 160,167 ****
118--- 160,176 ----
119  _DEFUN(_cleanup_r, (ptr),
120         struct _reent *ptr)
121  {
122+ #ifndef _STDIO_CLEANUP_NO_IO_SYSCALLS
123    _CAST_VOID _fwalk(ptr, fclose);
124    /* _CAST_VOID _fwalk (ptr, fflush); */      /* `cheating' */
125+ #else
126+   /* reclaim memory associated with FILEs attached to this
127+    * reent without performing any I/O operations (no fflush,
128+    * no close). E.g., RTEMS calls __reclaim_reent during thread
129+    * deletion when it is no longer safe to do I/O.
130+    */
131+   _CAST_VOID _fwalk(ptr, __reclaim_fp);
132+ #endif
133  }
134 
135  #ifndef _REENT_ONLY
136*** newlib-1.15.0/newlib/libc/stdio/local.h.cleanstdio.diff.orig        2006-09-26 14:22:19.000000000 -0700
137--- newlib-1.15.0/newlib/libc/stdio/local.h     2007-06-20 17:22:52.000000000 -0700
138***************
139*** 46,51 ****
140--- 46,53 ----
141  extern int    _EXFUN(_fwalk_reent,(struct _reent *, int (*)(struct _reent *, FILE *)));
142  struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n));
143 
144+ extern int    _EXFUN(__reclaim_fp,(FILE *));
145+
146  /* Called by the main entry point fns to ensure stdio has been initialized.  */
147 
148  #ifdef _REENT_SMALL