14
14
#include <stdio.h>
15
15
#include <stdlib.h>
16
16
#include <string.h>
17
+ #include <signal.h>
17
18
#ifdef _MSC_VER
18
19
/* For _alloca. */
19
20
#include <malloc.h>
@@ -59,6 +60,7 @@ static const char *getPNSStr(ProfileNameSpecifier PNS) {
59
60
}
60
61
61
62
#define MAX_PID_SIZE 16
63
+ #define MAX_SIGNAL_HANDLERS 16
62
64
/* Data structure holding the result of parsed filename pattern. */
63
65
typedef struct lprofFilename {
64
66
/* File name string possibly with %p or %h specifiers. */
@@ -79,11 +81,13 @@ typedef struct lprofFilename {
79
81
* 2 profile data files. %1m is equivalent to %m. Also %m specifier
80
82
* can only appear once at the end of the name pattern. */
81
83
unsigned MergePoolSize ;
84
+ char ExitOnSignals [MAX_SIGNAL_HANDLERS ];
85
+ unsigned NumExitSignals ;
82
86
ProfileNameSpecifier PNS ;
83
87
} lprofFilename ;
84
88
85
- COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0 , 0 , 0 , { 0 }, { 0 },
86
- 0 , 0 , 0 , PNS_unknown };
89
+ COMPILER_RT_WEAK lprofFilename lprofCurFilename = {
90
+ 0 , 0 , 0 , { 0 }, { 0 }, 0 , 0 , 0 , { 0 } , 0 , PNS_unknown };
87
91
88
92
int getpid (void );
89
93
static int getCurFilenameLength ();
@@ -252,6 +256,26 @@ static void truncateCurrentFile(void) {
252
256
fclose (File );
253
257
}
254
258
259
+ static void exitSignalHandler (int sig ) {
260
+ (void )sig ;
261
+ exit (0 );
262
+ }
263
+
264
+ static void installExitSignalHandlers (void ) {
265
+ unsigned I ;
266
+ struct sigaction sigact ;
267
+ int err ;
268
+ for (I = 0 ; I < lprofCurFilename .NumExitSignals ; ++ I ) {
269
+ memset (& sigact , 0 , sizeof (sigact ));
270
+ sigact .sa_handler = exitSignalHandler ;
271
+ err = sigaction (lprofCurFilename .ExitOnSignals [I ], & sigact , NULL );
272
+ if (err )
273
+ PROF_WARN (
274
+ "Unable to install an exit signal handler for %d (errno = %d).\n" ,
275
+ lprofCurFilename .ExitOnSignals [I ], err );
276
+ }
277
+ }
278
+
255
279
static const char * DefaultProfileName = "default.profraw" ;
256
280
static void resetFilenameToDefault (void ) {
257
281
if (lprofCurFilename .FilenamePat && lprofCurFilename .OwnsFilenamePat ) {
@@ -262,14 +286,23 @@ static void resetFilenameToDefault(void) {
262
286
lprofCurFilename .PNS = PNS_default ;
263
287
}
264
288
289
+ static int isNonZeroDigit (char C ) { return C >= '1' && C <= '9' ; }
290
+
265
291
static int containsMergeSpecifier (const char * FilenamePat , int I ) {
266
292
return (FilenamePat [I ] == 'm' ||
267
- (FilenamePat [I ] >= '1' && FilenamePat [ I ] <= '9' &&
293
+ (isNonZeroDigit ( FilenamePat [I ]) &&
268
294
/* If FilenamePat[I] is not '\0', the next byte is guaranteed
269
295
* to be in-bound as the string is null terminated. */
270
296
FilenamePat [I + 1 ] == 'm' ));
271
297
}
272
298
299
+ static int containsExitOnSignalSpecifier (const char * FilenamePat , int I ) {
300
+ if (!isNonZeroDigit (FilenamePat [I ]))
301
+ return 0 ;
302
+ return (FilenamePat [I + 1 ] == 'x' ) ||
303
+ (isNonZeroDigit (FilenamePat [I + 1 ]) && FilenamePat [I + 2 ] == 'x' );
304
+ }
305
+
273
306
/* Parses the pattern string \p FilenamePat and stores the result to
274
307
* lprofcurFilename structure. */
275
308
static int parseFilenamePattern (const char * FilenamePat ,
@@ -278,6 +311,7 @@ static int parseFilenamePattern(const char *FilenamePat,
278
311
char * PidChars = & lprofCurFilename .PidChars [0 ];
279
312
char * Hostname = & lprofCurFilename .Hostname [0 ];
280
313
int MergingEnabled = 0 ;
314
+ char SignalNo ;
281
315
282
316
/* Clean up cached prefix. */
283
317
if (lprofCurFilename .ProfilePathPrefix )
@@ -327,6 +361,22 @@ static int parseFilenamePattern(const char *FilenamePat,
327
361
lprofCurFilename .MergePoolSize = FilenamePat [I ] - '0' ;
328
362
I ++ ; /* advance to 'm' */
329
363
}
364
+ } else if (containsExitOnSignalSpecifier (FilenamePat , I )) {
365
+ if (lprofCurFilename .NumExitSignals == MAX_SIGNAL_HANDLERS ) {
366
+ PROF_WARN ("%%x specifier has been specified too many times in %s.\n" ,
367
+ FilenamePat );
368
+ return -1 ;
369
+ }
370
+ /* Grab the signal number. */
371
+ SignalNo = FilenamePat [I ] - '0' ;
372
+ I ++ ; /* advance to either another digit, or 'x' */
373
+ if (FilenamePat [I ] != 'x' ) {
374
+ SignalNo = (SignalNo * 10 ) + (FilenamePat [I ] - '0' );
375
+ I ++ ; /* advance to 'x' */
376
+ }
377
+ lprofCurFilename .ExitOnSignals [lprofCurFilename .NumExitSignals ] =
378
+ SignalNo ;
379
+ ++ lprofCurFilename .NumExitSignals ;
330
380
}
331
381
}
332
382
@@ -370,6 +420,7 @@ static void parseAndSetFilename(const char *FilenamePat,
370
420
}
371
421
372
422
truncateCurrentFile ();
423
+ installExitSignalHandlers ();
373
424
}
374
425
375
426
/* Return buffer length that is required to store the current profile
@@ -378,18 +429,24 @@ static void parseAndSetFilename(const char *FilenamePat,
378
429
#define SIGLEN 24
379
430
static int getCurFilenameLength () {
380
431
int Len ;
432
+ unsigned I ;
381
433
if (!lprofCurFilename .FilenamePat || !lprofCurFilename .FilenamePat [0 ])
382
434
return 0 ;
383
435
384
436
if (!(lprofCurFilename .NumPids || lprofCurFilename .NumHosts ||
385
- lprofCurFilename .MergePoolSize ))
437
+ lprofCurFilename .MergePoolSize || lprofCurFilename . NumExitSignals ))
386
438
return strlen (lprofCurFilename .FilenamePat );
387
439
388
440
Len = strlen (lprofCurFilename .FilenamePat ) +
389
441
lprofCurFilename .NumPids * (strlen (lprofCurFilename .PidChars ) - 2 ) +
390
442
lprofCurFilename .NumHosts * (strlen (lprofCurFilename .Hostname ) - 2 );
391
443
if (lprofCurFilename .MergePoolSize )
392
444
Len += SIGLEN ;
445
+ for (I = 0 ; I < lprofCurFilename .NumExitSignals ; ++ I ) {
446
+ Len -= 3 ; /* Drop the '%', signal number, and the 'x'. */
447
+ if (lprofCurFilename .ExitOnSignals [I ] >= 10 )
448
+ -- Len ; /* Drop the second digit of the signal number. */
449
+ }
393
450
return Len ;
394
451
}
395
452
@@ -405,7 +462,7 @@ static const char *getCurFilename(char *FilenameBuf) {
405
462
return 0 ;
406
463
407
464
if (!(lprofCurFilename .NumPids || lprofCurFilename .NumHosts ||
408
- lprofCurFilename .MergePoolSize ))
465
+ lprofCurFilename .MergePoolSize || lprofCurFilename . NumExitSignals ))
409
466
return lprofCurFilename .FilenamePat ;
410
467
411
468
PidLength = strlen (lprofCurFilename .PidChars );
@@ -431,6 +488,9 @@ static const char *getCurFilename(char *FilenameBuf) {
431
488
J += S ;
432
489
if (FilenamePat [I ] != 'm' )
433
490
I ++ ;
491
+ } else if (containsExitOnSignalSpecifier (FilenamePat , I )) {
492
+ while (FilenamePat [I ] != 'x' )
493
+ ++ I ;
434
494
}
435
495
/* Drop any unknown substitutions. */
436
496
} else
0 commit comments