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 |
---|