diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c
index dcfa79c0d..bd6832550 100644
--- a/cachegrind/cg_main.c
+++ b/cachegrind/cg_main.c
@@ -1256,9 +1256,6 @@ static CacheCC Dw_total;
static BranchCC Bc_total;
static BranchCC Bi_total;
-// The output file name. Controlled by --cachegrind-out-file.
-static Char* cachegrind_out_file = NULL;
-
static void fprint_CC_table_and_calc_totals(void)
{
Int i, fd;
@@ -1266,6 +1263,14 @@ static void fprint_CC_table_and_calc_totals(void)
Char buf[512], *currFile = NULL, *currFn = NULL;
LineCC* lineCC;
+ // Setup output filename. Nb: it's important to do this now, ie. as late
+ // as possible. If we do it at start-up and the program forks and the
+ // output file format string contains a %p (pid) specifier, both the
+ // parent and child will incorrectly write to the same file; this
+ // happened in 3.3.0.
+ Char* cachegrind_out_file =
+ VG_(expand_file_name)("--cachegrind-out-file", clo_cachegrind_out_file);
+
sres = VG_(open)(cachegrind_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY,
VKI_S_IRUSR|VKI_S_IWUSR);
if (sres.isError) {
@@ -1276,9 +1281,11 @@ static void fprint_CC_table_and_calc_totals(void)
cachegrind_out_file );
VG_(message)(Vg_UserMsg,
" ... so simulation results will be missing.");
+ VG_(free)(cachegrind_out_file);
return;
} else {
fd = sres.res;
+ VG_(free)(cachegrind_out_file);
}
// "desc:" lines (giving I1/D1/L2 cache configuration). The spaces after
@@ -1752,10 +1759,6 @@ static void cg_post_clo_init(void)
VG_(exit)(2);
}
- // Setup output filename.
- cachegrind_out_file =
- VG_(expand_file_name)("--cachegrind-out-file", clo_cachegrind_out_file);
-
CC_table =
VG_(OSetGen_Create)(offsetof(LineCC, loc),
cmp_CodeLoc_LineCC,
diff --git a/cachegrind/docs/cg-manual.xml b/cachegrind/docs/cg-manual.xml
index 30857fa9f..7c1764e00 100644
--- a/cachegrind/docs/cg-manual.xml
+++ b/cachegrind/docs/cg-manual.xml
@@ -820,6 +820,19 @@ way as for C/C++ programs.
+
+Forking Programs
+If your program forks, the child will inherit all the profiling data that
+has been gathered for the parent.
+
+If the output file format string (controlled by
+) does not contain ,
+then the outputs from the parent and child will be intermingled in a single
+output file, which will almost certainly make it unreadable by
+cg_annotate.
+
+
+
diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml
index 236b835be..285512034 100644
--- a/docs/xml/manual-core.xml
+++ b/docs/xml/manual-core.xml
@@ -714,7 +714,8 @@ categories.
is replaced with the current process ID.
This is very useful for program that invoke multiple processes.
WARNING: If you use and your
- program invokes multiple processes and you don't use this specifier
+ program invokes multiple processes OR your program forks without
+ calling exec afterwards, and you don't use this specifier
(or the specifier below), the Valgrind output from
all those processes will go into one file, possibly jumbled up, and
possibly incomplete.
diff --git a/massif/docs/ms-manual.xml b/massif/docs/ms-manual.xml
index 7ff37cdaf..81a066eec 100644
--- a/massif/docs/ms-manual.xml
+++ b/massif/docs/ms-manual.xml
@@ -494,12 +494,23 @@ responsible for more than 1% of useful memory bytes, and ms_print likewise
only prints the details for code locations responsible for more than 1%.
The entries that do not meet this threshold are aggregated. This avoids
filling up the output with large numbers of unimportant entries. The
-thresholds threshold can be changed with the
+thresholds can be changed with the
--threshold option that both Massif and
ms_print support.
+
+Forking Programs
+If your program forks, the child will inherit all the profiling data that
+has been gathered for the parent.
+
+If the output file format string (controlled by
+) does not contain , then
+the outputs from the parent and child will be intermingled in a single output
+file, which will almost certainly make it unreadable by ms_print.
+
+
diff --git a/massif/ms_main.c b/massif/ms_main.c
index 1f9d14c36..1631fe2ce 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -1866,9 +1866,6 @@ IRSB* ms_instrument ( VgCallbackClosure* closure,
//--- Writing snapshots ---//
//------------------------------------------------------------//
-// The output file name. Controlled by --massif-out-file.
-static Char* massif_out_file = NULL;
-
Char FP_buf[BUF_LEN];
// XXX: implement f{,n}printf in m_libcprint.c eventually, and use it here.
@@ -2041,6 +2038,14 @@ static void write_snapshots_to_file(void)
Int i, fd;
SysRes sres;
+ // Setup output filename. Nb: it's important to do this now, ie. as late
+ // as possible. If we do it at start-up and the program forks and the
+ // output file format string contains a %p (pid) specifier, both the
+ // parent and child will incorrectly write to the same file; this
+ // happened in 3.3.0.
+ Char* massif_out_file =
+ VG_(expand_file_name)("--massif-out-file", clo_massif_out_file);
+
sres = VG_(open)(massif_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY,
VKI_S_IRUSR|VKI_S_IWUSR);
if (sres.isError) {
@@ -2050,9 +2055,11 @@ static void write_snapshots_to_file(void)
"error: can't open output file '%s'", massif_out_file );
VG_(message)(Vg_UserMsg,
" ... so profiling results will be missing.");
+ VG_(free)(massif_out_file);
return;
} else {
fd = sres.res;
+ VG_(free)(massif_out_file);
}
// Print massif-specific options that were used.
@@ -2184,10 +2191,6 @@ static void ms_post_clo_init(void)
clear_snapshot( & snapshots[i], /*do_sanity_check*/False );
}
sanity_check_snapshots_array();
-
- // Setup output filename.
- massif_out_file =
- VG_(expand_file_name)("--massif-out-file", clo_massif_out_file);
}
static void ms_pre_clo_init(void)