From: Josef Weidendorfer Date: Wed, 20 Sep 2006 21:29:39 +0000 (+0000) Subject: Callgrind: fix interactive control after fork() X-Git-Tag: svn/VALGRIND_3_3_0~668 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0d463585d9dcdf9417bc4daf6275a76d620bca71;p=thirdparty%2Fvalgrind.git Callgrind: fix interactive control after fork() This fixes bug 134316: when an program in callgrind does a fork, callgrind_control does show both now, and they can be controlled separately. However, missing in this patch is zeroing of cost centers directly after the clone syscall in the child. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6082 --- diff --git a/callgrind/command.c b/callgrind/command.c index 10ad909c24..edbd6d5c80 100644 --- a/callgrind/command.c +++ b/callgrind/command.c @@ -48,20 +48,35 @@ static Char* current_result_file = 0; static Char* info_file = 0; static Char* dump_base = 0; -static Bool command_inited = False; +static Int thisPID = 0; -void CLG_(init_command)(Char* dir, Char* dumps) +/** + * Setup for interactive control of a callgrind run + */ +static void setup_control(void) { - Int fd = -1, size; + Int fd, size; SysRes res; + Char* dir, *dump_filename; + + CLG_ASSERT(thisPID != 0); + + fd = -1; + dir = CLG_(get_base_directory)(); + dump_base = CLG_(get_dump_file_base)(); - dump_base = dumps; + /* base name of dump files with PID ending */ + size = VG_(strlen)(dump_base) + 10; + dump_filename = (char*) CLG_MALLOC(size); + CLG_ASSERT(dump_filename != 0); + VG_(sprintf)(dump_filename, "%s.%d", dump_base, thisPID); + /* name of command file */ size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_COMMANDNAME) +10; command_file = (char*) CLG_MALLOC(size); CLG_ASSERT(command_file != 0); VG_(sprintf)(command_file, "%s/%s.%d", - dir, DEFAULT_COMMANDNAME, VG_(getpid)()); + dir, DEFAULT_COMMANDNAME, thisPID); /* This is for compatibility with the "Force Now" Button of current * KCachegrind releases, as it doesn't use ".pid" to distinguish @@ -76,7 +91,7 @@ void CLG_(init_command)(Char* dir, Char* dumps) result_file = (char*) CLG_MALLOC(size); CLG_ASSERT(result_file != 0); VG_(sprintf)(result_file, "%s/%s.%d", - dir, DEFAULT_RESULTNAME, VG_(getpid)()); + dir, DEFAULT_RESULTNAME, thisPID); /* If we get a command from a command file without .pid, use * a result file without .pid suffix @@ -88,9 +103,10 @@ void CLG_(init_command)(Char* dir, Char* dumps) info_file = (char*) CLG_MALLOC(VG_(strlen)(DEFAULT_INFONAME) + 10); CLG_ASSERT(info_file != 0); - VG_(sprintf)(info_file, "%s.%d", DEFAULT_INFONAME, VG_(getpid)()); + VG_(sprintf)(info_file, "%s.%d", DEFAULT_INFONAME, thisPID); - CLG_DEBUG(1, " dump file base: '%s'\n", dump_base); + CLG_DEBUG(1, "Setup for interactive control (PID: %d):\n", thisPID); + CLG_DEBUG(1, " dump file base: '%s'\n", dump_filename); CLG_DEBUG(1, " command file: '%s'\n", command_file); CLG_DEBUG(1, " result file: '%s'\n", result_file); CLG_DEBUG(1, " info file: '%s'\n", info_file); @@ -128,7 +144,7 @@ void CLG_(init_command)(Char* dir, Char* dumps) VG_(sprintf)(buf, "base: %s\n", dir); VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - VG_(sprintf)(buf, "dumps: %s\n", dump_base); + VG_(sprintf)(buf, "dumps: %s\n", dump_filename); VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); VG_(sprintf)(buf, "control: %s\n", command_file); @@ -149,8 +165,12 @@ void CLG_(init_command)(Char* dir, Char* dumps) VG_(write)(fd, "\n", 1); VG_(close)(fd); } +} - command_inited = True; +void CLG_(init_command)() +{ + thisPID = VG_(getpid)(); + setup_control(); } void CLG_(finish_command)() @@ -355,14 +375,31 @@ void CLG_(check_command)() Char *cmdPos = 0, *cmdNextLine = 0; Int fd, bytesRead = 0, do_kill = 0; SysRes res; + Int currentPID; + static Int check_counter = 0; - if (!command_inited) return; + /* Check for PID change, i.e. whether we run as child after a fork. + * If yes, we setup interactive control for the new process + */ + currentPID = VG_(getpid)(); + if (thisPID != currentPID) { + thisPID = currentPID; + setup_control(); + } - /* toggle between 2 command files, with/without ".pid" postfix */ - current_command_file = (current_command_file == command_file2) ? - command_file : command_file2; - current_result_file = (current_command_file == command_file2) ? - result_file2 : result_file; + /* Toggle between 2 command files, with/without ".pid" postfix + * (needed for compatibility with KCachegrind, which wants to trigger + * a dump by writing into a command file without the ".pid" postfix) + */ + check_counter++; + if (check_counter % 2) { + current_command_file = command_file; + current_result_file = result_file; + } + else { + current_command_file = command_file2; + current_result_file = result_file2; + } res = VG_(open)(current_command_file, VKI_O_RDONLY,0); if (!res.isError) { diff --git a/callgrind/dump.c b/callgrind/dump.c index ae730c7c9c..f9bc6521c3 100644 --- a/callgrind/dump.c +++ b/callgrind/dump.c @@ -32,15 +32,13 @@ #include #include -/*------------------------------------------------------------*/ -/*--- Support for signal handlers and multi-threading ---*/ -/*------------------------------------------------------------*/ /* Dump Part Counter */ static Int out_counter = 0; static Char* dump_file_base = 0; static Char* base_directory = 0; +static Bool dumps_initialized = False; /* Command */ static Char cmdbuf[BUF_LEN]; @@ -66,7 +64,14 @@ Int CLG_(get_dump_counter)(void) Char* CLG_(get_dump_file_base)() { - return dump_file_base; + CLG_ASSERT(dumps_initialized); + return dump_file_base; +} + +Char* CLG_(get_base_directory)() +{ + CLG_ASSERT(dumps_initialized); + return base_directory; } /*------------------------------------------------------------*/ @@ -1264,6 +1269,7 @@ static int new_dumpfile(Char buf[BUF_LEN], int tid, Char* trigger) FullCost sum = 0; SysRes res; + CLG_ASSERT(dumps_initialized); CLG_ASSERT(filename != 0); if (!CLG_(clo).combine_dumps) { @@ -1641,10 +1647,20 @@ void init_cmdbuf(void) cmdbuf[size] = 0; } -void CLG_(init_files)(Char** dir, Char** file) +/* + * Set up file names for dump output: base_directory, dump_file_base + * The final filename of a dump is constructed at dump time from + * the PID, thread ID and dump counter. + * + * These always will contain a full absolute path. + * If no prefix is given (via option "--base="), the current + * working directory at program start is used, otherwise can + * be relative to cwd or absolute. + */ +void CLG_(init_dumps)() { - Int size; - SysRes res; + Int size; + SysRes res; if (!CLG_(clo).filename_base) CLG_(clo).filename_base = DEFAULT_DUMPNAME; @@ -1709,8 +1725,7 @@ void CLG_(init_files)(Char** dir, Char** file) } if (!res.isError) VG_(close)( (Int)res.val ); - *dir = base_directory; - *file = filename; - init_cmdbuf(); + + dumps_initialized = True; } diff --git a/callgrind/global.h b/callgrind/global.h index 0079b4d3a0..335de14618 100644 --- a/callgrind/global.h +++ b/callgrind/global.h @@ -675,7 +675,7 @@ Int CLG_(get_dump_counter)(void); void CLG_(fini)(Int exitcode); /* from command.c */ -void CLG_(init_command)(Char* dir, Char* dumps); +void CLG_(init_command)(void); void CLG_(check_command)(void); void CLG_(finish_command)(void); @@ -761,9 +761,9 @@ void CLG_(run_post_signal_on_call_stack_bottom)(void); /* from dump.c */ extern FullCost CLG_(total_cost); -void CLG_(init_files)(Char** dir, Char** file); +void CLG_(init_dumps)(void); Char* CLG_(get_dump_file_base)(void); - +Char* CLG_(get_base_directory)(void); /*------------------------------------------------------------*/ /*--- Exported global variables ---*/ diff --git a/callgrind/main.c b/callgrind/main.c index aa88a9df3c..d0c0f4052d 100644 --- a/callgrind/main.c +++ b/callgrind/main.c @@ -1028,8 +1028,6 @@ void CLG_(fini)(Int exitcode) static void CLG_(post_clo_init)(void) { - Char *dir = 0, *fname = 0; - VG_(clo_vex_control).iropt_unroll_thresh = 0; VG_(clo_vex_control).guest_chase_thresh = 0; @@ -1042,8 +1040,8 @@ void CLG_(post_clo_init)(void) CLG_(clo).dump_line = True; } - CLG_(init_files)(&dir,&fname); - CLG_(init_command)(dir,fname); + CLG_(init_dumps)(); + CLG_(init_command)(); (*CLG_(cachesim).post_clo_init)();