12
12
#include <stdio.h>
13
13
#include <stdlib.h>
14
14
#include <string.h>
15
+ #include <signal.h>
15
16
#ifdef _MSC_VER
16
17
/* For _alloca. */
17
18
#include <malloc.h>
@@ -62,6 +63,7 @@ static const char *getPNSStr(ProfileNameSpecifier PNS) {
62
63
}
63
64
64
65
#define MAX_PID_SIZE 16
66
+ #define MAX_SIGNAL_HANDLERS 16
65
67
/* Data structure holding the result of parsed filename pattern. */
66
68
typedef struct lprofFilename {
67
69
/* File name string possibly with %p or %h specifiers. */
@@ -83,11 +85,14 @@ typedef struct lprofFilename {
83
85
* 2 profile data files. %1m is equivalent to %m. Also %m specifier
84
86
* can only appear once at the end of the name pattern. */
85
87
unsigned MergePoolSize ;
88
+ char ExitOnSignals [MAX_SIGNAL_HANDLERS ];
89
+ unsigned NumExitSignals ;
86
90
ProfileNameSpecifier PNS ;
87
91
} lprofFilename ;
88
92
89
93
COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0 , 0 , 0 , 0 , {0 },
90
- {0 }, 0 , 0 , 0 , PNS_unknown };
94
+ {0 }, 0 , 0 , 0 , {0 }, 0 ,
95
+ PNS_unknown };
91
96
92
97
static int getCurFilenameLength ();
93
98
static const char * getCurFilename (char * FilenameBuf , int ForceUseBuf );
@@ -286,6 +291,19 @@ static void truncateCurrentFile(void) {
286
291
fclose (File );
287
292
}
288
293
294
+ static void exitSignalHandler (int sig ) {
295
+ (void )sig ;
296
+ exit (0 );
297
+ }
298
+
299
+ static void installExitSignalHandlers (void ) {
300
+ unsigned I ;
301
+ for (I = 0 ; I < lprofCurFilename .NumExitSignals ; ++ I ) {
302
+ lprofInstallSignalHandler (lprofCurFilename .ExitOnSignals [I ],
303
+ exitSignalHandler );
304
+ }
305
+ }
306
+
289
307
static const char * DefaultProfileName = "default.profraw" ;
290
308
static void resetFilenameToDefault (void ) {
291
309
if (lprofCurFilename .FilenamePat && lprofCurFilename .OwnsFilenamePat ) {
@@ -296,14 +314,25 @@ static void resetFilenameToDefault(void) {
296
314
lprofCurFilename .PNS = PNS_default ;
297
315
}
298
316
317
+ static int isDigit (char C ) { return C >= '0' && C <= '9' ; }
318
+
319
+ static int isNonZeroDigit (char C ) { return C >= '1' && C <= '9' ; }
320
+
299
321
static int containsMergeSpecifier (const char * FilenamePat , int I ) {
300
322
return (FilenamePat [I ] == 'm' ||
301
- (FilenamePat [I ] >= '1' && FilenamePat [ I ] <= '9' &&
323
+ (isNonZeroDigit ( FilenamePat [I ]) &&
302
324
/* If FilenamePat[I] is not '\0', the next byte is guaranteed
303
325
* to be in-bound as the string is null terminated. */
304
326
FilenamePat [I + 1 ] == 'm' ));
305
327
}
306
328
329
+ static int containsExitOnSignalSpecifier (const char * FilenamePat , int I ) {
330
+ if (!isNonZeroDigit (FilenamePat [I ]))
331
+ return 0 ;
332
+ return (FilenamePat [I + 1 ] == 'x' ) ||
333
+ (isDigit (FilenamePat [I + 1 ]) && FilenamePat [I + 2 ] == 'x' );
334
+ }
335
+
307
336
/* Parses the pattern string \p FilenamePat and stores the result to
308
337
* lprofcurFilename structure. */
309
338
static int parseFilenamePattern (const char * FilenamePat ,
@@ -312,6 +341,7 @@ static int parseFilenamePattern(const char *FilenamePat,
312
341
char * PidChars = & lprofCurFilename .PidChars [0 ];
313
342
char * Hostname = & lprofCurFilename .Hostname [0 ];
314
343
int MergingEnabled = 0 ;
344
+ char SignalNo ;
315
345
316
346
/* Clean up cached prefix and filename. */
317
347
if (lprofCurFilename .ProfilePathPrefix )
@@ -364,6 +394,22 @@ static int parseFilenamePattern(const char *FilenamePat,
364
394
lprofCurFilename .MergePoolSize = FilenamePat [I ] - '0' ;
365
395
I ++ ; /* advance to 'm' */
366
396
}
397
+ } else if (containsExitOnSignalSpecifier (FilenamePat , I )) {
398
+ if (lprofCurFilename .NumExitSignals == MAX_SIGNAL_HANDLERS ) {
399
+ PROF_WARN ("%%x specifier has been specified too many times in %s.\n" ,
400
+ FilenamePat );
401
+ return -1 ;
402
+ }
403
+ /* Grab the signal number. */
404
+ SignalNo = FilenamePat [I ] - '0' ;
405
+ I ++ ; /* advance to either another digit, or 'x' */
406
+ if (FilenamePat [I ] != 'x' ) {
407
+ SignalNo = (SignalNo * 10 ) + (FilenamePat [I ] - '0' );
408
+ I ++ ; /* advance to 'x' */
409
+ }
410
+ lprofCurFilename .ExitOnSignals [lprofCurFilename .NumExitSignals ] =
411
+ SignalNo ;
412
+ ++ lprofCurFilename .NumExitSignals ;
367
413
}
368
414
}
369
415
@@ -407,6 +453,7 @@ static void parseAndSetFilename(const char *FilenamePat,
407
453
}
408
454
409
455
truncateCurrentFile ();
456
+ installExitSignalHandlers ();
410
457
}
411
458
412
459
/* Return buffer length that is required to store the current profile
@@ -415,18 +462,24 @@ static void parseAndSetFilename(const char *FilenamePat,
415
462
#define SIGLEN 24
416
463
static int getCurFilenameLength () {
417
464
int Len ;
465
+ unsigned I ;
418
466
if (!lprofCurFilename .FilenamePat || !lprofCurFilename .FilenamePat [0 ])
419
467
return 0 ;
420
468
421
469
if (!(lprofCurFilename .NumPids || lprofCurFilename .NumHosts ||
422
- lprofCurFilename .MergePoolSize ))
470
+ lprofCurFilename .MergePoolSize || lprofCurFilename . NumExitSignals ))
423
471
return strlen (lprofCurFilename .FilenamePat );
424
472
425
473
Len = strlen (lprofCurFilename .FilenamePat ) +
426
474
lprofCurFilename .NumPids * (strlen (lprofCurFilename .PidChars ) - 2 ) +
427
475
lprofCurFilename .NumHosts * (strlen (lprofCurFilename .Hostname ) - 2 );
428
476
if (lprofCurFilename .MergePoolSize )
429
477
Len += SIGLEN ;
478
+ for (I = 0 ; I < lprofCurFilename .NumExitSignals ; ++ I ) {
479
+ Len -= 3 ; /* Drop the '%', signal number, and the 'x'. */
480
+ if (lprofCurFilename .ExitOnSignals [I ] >= 10 )
481
+ -- Len ; /* Drop the second digit of the signal number. */
482
+ }
430
483
return Len ;
431
484
}
432
485
@@ -443,7 +496,7 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
443
496
return 0 ;
444
497
445
498
if (!(lprofCurFilename .NumPids || lprofCurFilename .NumHosts ||
446
- lprofCurFilename .MergePoolSize )) {
499
+ lprofCurFilename .MergePoolSize || lprofCurFilename . NumExitSignals )) {
447
500
if (!ForceUseBuf )
448
501
return lprofCurFilename .FilenamePat ;
449
502
@@ -476,6 +529,9 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
476
529
J += S ;
477
530
if (FilenamePat [I ] != 'm' )
478
531
I ++ ;
532
+ } else if (containsExitOnSignalSpecifier (FilenamePat , I )) {
533
+ while (FilenamePat [I ] != 'x' )
534
+ ++ I ;
479
535
}
480
536
/* Drop any unknown substitutions. */
481
537
} else
0 commit comments