@@ -148,35 +148,108 @@ int qmem_walk(qmem_walk_fn *func, void *arg)
148
148
}
149
149
150
150
struct exit_dump_args {
151
- FILE * fp ;
152
- const char * prefix ;
151
+ const char * daemon_name ;
152
+ bool do_log ;
153
+ bool do_file ;
154
+ bool do_stderr ;
153
155
int error ;
156
+ FILE * fp ;
157
+ struct memgroup * last_mg ;
154
158
};
155
159
160
+ static void qmem_exit_fopen (struct exit_dump_args * eda )
161
+ {
162
+ char filename [128 ];
163
+
164
+ if (eda -> fp || !eda -> do_file || !eda -> daemon_name )
165
+ return ;
166
+
167
+ snprintf (filename , sizeof (filename ), "/tmp/frr-memstats-%s-%llu-%llu" , eda -> daemon_name ,
168
+ (unsigned long long )getpid (), (unsigned long long )time (NULL ));
169
+ eda -> fp = fopen (filename , "w" );
170
+
171
+ if (!eda -> fp ) {
172
+ zlog_err ("failed to open memstats dump file %pSQq: %m" , filename );
173
+ /* don't try opening file over and over again */
174
+ eda -> do_file = false;
175
+ }
176
+ }
177
+
156
178
static int qmem_exit_walker (void * arg , struct memgroup * mg , struct memtype * mt )
157
179
{
158
180
struct exit_dump_args * eda = arg ;
181
+ const char * prefix = eda -> daemon_name ?: "NONE" ;
182
+ char size [32 ];
183
+
184
+ if (!mt )
185
+ /* iterator calls mg=X, mt=NULL first */
186
+ return 0 ;
159
187
160
- if (!mt ) {
161
- fprintf (eda -> fp ,
162
- "%s: showing active allocations in memory group %s\n" ,
163
- eda -> prefix , mg -> name );
188
+ if (!mt -> n_alloc )
189
+ return 0 ;
164
190
165
- } else if (mt -> n_alloc ) {
166
- char size [32 ];
167
- if (!mg -> active_at_exit )
168
- eda -> error ++ ;
191
+ if (mt -> size != SIZE_VAR )
169
192
snprintf (size , sizeof (size ), "%10zu" , mt -> size );
170
- fprintf (eda -> fp , "%s: memstats: %-30s: %6zu * %s\n" ,
171
- eda -> prefix , mt -> name , mt -> n_alloc ,
172
- mt -> size == SIZE_VAR ? "(variably sized)" : size );
193
+ else
194
+ snprintf (size , sizeof (size ), "(variably sized)" );
195
+
196
+ if (mg -> active_at_exit ) {
197
+ /* not an error - this memgroup has allocations remain active
198
+ * at exit. Only printed to zlog_debug.
199
+ */
200
+ if (!eda -> do_log )
201
+ return 0 ;
202
+
203
+ if (eda -> last_mg != mg ) {
204
+ zlog_debug ("showing active allocations in memory group %s (not an error)" ,
205
+ mg -> name );
206
+ eda -> last_mg = mg ;
207
+ }
208
+ zlog_debug ("memstats: %-30s: %6zu * %s" , mt -> name , mt -> n_alloc , size );
209
+ return 0 ;
173
210
}
211
+
212
+ eda -> error ++ ;
213
+ if (eda -> do_file )
214
+ qmem_exit_fopen (eda );
215
+
216
+ if (eda -> last_mg != mg ) {
217
+ if (eda -> do_log )
218
+ zlog_warn ("showing active allocations in memory group %s" , mg -> name );
219
+ if (eda -> do_stderr )
220
+ fprintf (stderr , "%s: showing active allocations in memory group %s\n" ,
221
+ prefix , mg -> name );
222
+ if (eda -> fp )
223
+ fprintf (eda -> fp , "%s: showing active allocations in memory group %s\n" ,
224
+ prefix , mg -> name );
225
+ eda -> last_mg = mg ;
226
+ }
227
+
228
+ if (eda -> do_log )
229
+ zlog_warn ("memstats: %-30s: %6zu * %s" , mt -> name , mt -> n_alloc , size );
230
+ if (eda -> do_stderr )
231
+ fprintf (stderr , "%s: memstats: %-30s: %6zu * %s\n" , prefix , mt -> name , mt -> n_alloc ,
232
+ size );
233
+ if (eda -> fp )
234
+ fprintf (eda -> fp , "%s: memstats: %-30s: %6zu * %s\n" , prefix , mt -> name , mt -> n_alloc ,
235
+ size );
174
236
return 0 ;
175
237
}
176
238
177
- int log_memstats (FILE * fp , const char * prefix )
239
+ int log_memstats (const char * daemon_name , bool enabled )
178
240
{
179
- struct exit_dump_args eda = {.fp = fp , .prefix = prefix , .error = 0 };
241
+ struct exit_dump_args eda = {
242
+ .daemon_name = daemon_name ,
243
+ .do_log = enabled ,
244
+ .do_file = enabled ,
245
+ .do_stderr = enabled || !isatty (STDERR_FILENO ),
246
+ .error = 0 ,
247
+ };
248
+
180
249
qmem_walk (qmem_exit_walker , & eda );
250
+ if (eda .fp )
251
+ fclose (eda .fp );
252
+ if (eda .error && eda .do_log )
253
+ zlog_warn ("exiting with %d leaked MTYPEs" , eda .error );
181
254
return eda .error ;
182
255
}
0 commit comments