summaryrefslogtreecommitdiffstats
path: root/tools/valgrind/fork.patch
blob: 9802318c09d8948ae60606950737ba0a2ff26af3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
Index: coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- coregrind/m_syswrap/syswrap-generic.c	(revision 10880)
+++ coregrind/m_syswrap/syswrap-generic.c	(working copy)
@@ -2563,6 +2563,11 @@
 
    } else {
       path = (Char*)ARG1;
+      if (VG_(clo_xml)) {
+        VG_(printf_xml)("\n<execv/>\n\n</valgrindoutput>\n\n");
+      } else {
+        VG_(umsg)("execv called - the tool will now quit\n");
+      }
    }
 
    // Set up the child's environment.
@@ -4103,4 +4108,3 @@
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
-
Index: coregrind/pub_core_libcfile.h
===================================================================
--- coregrind/pub_core_libcfile.h	(revision 10880)
+++ coregrind/pub_core_libcfile.h	(working copy)
@@ -41,6 +41,7 @@
 
 /* Move an fd into the Valgrind-safe range */
 extern Int VG_(safe_fd) ( Int oldfd );
+extern Int reopen_output_fd(Bool xml);
 extern Int VG_(fcntl)   ( Int fd, Int cmd, Addr arg );
 
 /* Convert an fd into a filename */
Index: coregrind/m_main.c
===================================================================
--- coregrind/m_main.c	(revision 10880)
+++ coregrind/m_main.c	(working copy)
@@ -313,6 +313,64 @@
    }
 }
 
+Int reopen_output_fd(Bool xml) {
+  // Returns FD
+  Char *filename = NULL;
+  Char *fsname_unexpanded = xml ? VG_(clo_xml_fname_unexpanded) :
+                                 VG_(clo_log_fname_unexpanded);
+  const Char *output_type = xml ? "xml" : "log";
+  Int ret = -1;
+  SysRes sres;
+
+  vg_assert(fsname_unexpanded != NULL);
+  vg_assert(VG_(strlen)(fsname_unexpanded) <= 900); /* paranoia */
+
+  // Nb: we overwrite an existing file of this name without asking
+  // any questions.
+  filename = VG_(expand_file_name)(xml ? "--xml-file" : "--log-file",
+                                   fsname_unexpanded);
+  sres = VG_(open)(filename,
+                   VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
+                   VKI_S_IRUSR|VKI_S_IWUSR);
+  if (!sr_isError(sres)) {
+    ret = sr_Res(sres);
+    if (xml)
+      VG_(clo_xml_fname_expanded) = filename;
+    else
+      VG_(clo_log_fname_expanded) = filename;
+
+    /* strdup here is probably paranoid overkill, but ... */
+    // TODO: do we need to do anything with it?
+    /* *fsname_unexpanded = VG_(strdup)( "main.mpclo.2",
+                                         xml_fsname_unexpanded ); */
+  } else {
+    VG_(message)(Vg_UserMsg,
+                 "Can't create %s file '%s' (%s); giving up!\n",
+                 output_type, filename, VG_(strerror)(sr_Err(sres)));
+    VG_(err_bad_option)(
+        "--[xml|log]-file=<file> (didn't work out for some reason.)");
+    /*NOTREACHED*/
+  }
+
+  return ret;
+}
+
+static Int move_fd_into_safe_range(Int fd, Bool xml) {
+   OutputSink *sink = xml ? &(VG_(xml_output_sink)) : &(VG_(log_output_sink));
+   // Move fd into the safe range, so it doesn't conflict with any app fds.
+   fd = VG_(fcntl)(fd, VKI_F_DUPFD, VG_(fd_hard_limit));
+   if (fd < 0) {
+      VG_(printf)("valgrind: failed to move %s file fd "
+                  "into safe range, using stderr\n", xml ? "XML" : "log");
+      sink->fd = 2;   // stderr
+      sink->is_socket = False;
+   } else {
+      sink->fd = fd;
+      VG_(fcntl)(fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
+   }
+   return fd;
+}
+
 /* The main processing for command line options.  See comments above
    on early_process_cmd_line_options.
 
@@ -339,13 +397,11 @@
 */
 static
 void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd,
-                                     /*OUT*/Char** xml_fname_unexpanded,
                                      const HChar* toolname )
 {
    // VG_(clo_log_fd) is used by all the messaging.  It starts as 2 (stderr)
    // and we cannot change it until we know what we are changing it to is
    // ok.  So we have tmp_log_fd to hold the tmp fd prior to that point.
-   SysRes sres;
    Int    i, tmp_log_fd, tmp_xml_fd;
    Int    toolname_len = VG_(strlen)(toolname);
    Char*  tmp_str;         // Used in a couple of places.
@@ -514,9 +570,13 @@
 
       else if VG_STR_CLO(arg, "--log-file", log_fsname_unexpanded) {
          log_to = VgLogTo_File;
+         VG_(clo_log_fname_unexpanded) =
+             VG_(strdup)("", log_fsname_unexpanded);
       }
       else if VG_STR_CLO(arg, "--xml-file", xml_fsname_unexpanded) {
          xml_to = VgLogTo_File;
+         VG_(clo_xml_fname_unexpanded) =
+             VG_(strdup)("", xml_fsname_unexpanded);
       }
  
       else if VG_STR_CLO(arg, "--log-socket", log_fsname_unexpanded) {
@@ -716,29 +776,7 @@
          break;
 
       case VgLogTo_File: {
-         Char* logfilename;
-
-         vg_assert(log_fsname_unexpanded != NULL);
-         vg_assert(VG_(strlen)(log_fsname_unexpanded) <= 900); /* paranoia */
-
-         // Nb: we overwrite an existing file of this name without asking
-         // any questions.
-         logfilename = VG_(expand_file_name)("--log-file",
-                                             log_fsname_unexpanded);
-         sres = VG_(open)(logfilename, 
-                          VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC, 
-                          VKI_S_IRUSR|VKI_S_IWUSR);
-         if (!sr_isError(sres)) {
-            tmp_log_fd = sr_Res(sres);
-            VG_(clo_log_fname_expanded) = logfilename;
-         } else {
-            VG_(message)(Vg_UserMsg, 
-                         "Can't create log file '%s' (%s); giving up!\n", 
-                         logfilename, VG_(strerror)(sr_Err(sres)));
-            VG_(err_bad_option)(
-               "--log-file=<file> (didn't work out for some reason.)");
-            /*NOTREACHED*/
-         }
+         tmp_log_fd = reopen_output_fd(False);
          break;
       }
 
@@ -784,32 +822,7 @@
          break;
 
       case VgLogTo_File: {
-         Char* xmlfilename;
-
-         vg_assert(xml_fsname_unexpanded != NULL);
-         vg_assert(VG_(strlen)(xml_fsname_unexpanded) <= 900); /* paranoia */
-
-         // Nb: we overwrite an existing file of this name without asking
-         // any questions.
-         xmlfilename = VG_(expand_file_name)("--xml-file",
-                                             xml_fsname_unexpanded);
-         sres = VG_(open)(xmlfilename, 
-                          VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC, 
-                          VKI_S_IRUSR|VKI_S_IWUSR);
-         if (!sr_isError(sres)) {
-            tmp_xml_fd = sr_Res(sres);
-            VG_(clo_xml_fname_expanded) = xmlfilename;
-            /* strdup here is probably paranoid overkill, but ... */
-            *xml_fname_unexpanded = VG_(strdup)( "main.mpclo.2",
-                                                 xml_fsname_unexpanded );
-         } else {
-            VG_(message)(Vg_UserMsg, 
-                         "Can't create XML file '%s' (%s); giving up!\n", 
-                         xmlfilename, VG_(strerror)(sr_Err(sres)));
-            VG_(err_bad_option)(
-               "--xml-file=<file> (didn't work out for some reason.)");
-            /*NOTREACHED*/
-         }
+         tmp_xml_fd = reopen_output_fd(True);
          break;
       }
 
@@ -864,18 +877,7 @@
    // Finalise the output fds: the log fd ..
 
    if (tmp_log_fd >= 0) {
-      // Move log_fd into the safe range, so it doesn't conflict with
-      // any app fds.
-      tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
-      if (tmp_log_fd < 0) {
-         VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd "
-                                  "into safe range, using stderr\n");
-         VG_(log_output_sink).fd = 2;   // stderr
-         VG_(log_output_sink).is_socket = False;
-      } else {
-         VG_(log_output_sink).fd = tmp_log_fd;
-         VG_(fcntl)(VG_(log_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
-      }
+      tmp_log_fd = move_fd_into_safe_range(tmp_log_fd, False);
    } else {
       // If they said --log-fd=-1, don't print anything.  Plausible for use in
       // regression testing suites that use client requests to count errors.
@@ -886,18 +888,7 @@
    // Finalise the output fds: and the XML fd ..
 
    if (tmp_xml_fd >= 0) {
-      // Move xml_fd into the safe range, so it doesn't conflict with
-      // any app fds.
-      tmp_xml_fd = VG_(fcntl)(tmp_xml_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
-      if (tmp_xml_fd < 0) {
-         VG_(message)(Vg_UserMsg, "valgrind: failed to move XML file fd "
-                                  "into safe range, using stderr\n");
-         VG_(xml_output_sink).fd = 2;   // stderr
-         VG_(xml_output_sink).is_socket = False;
-      } else {
-         VG_(xml_output_sink).fd = tmp_xml_fd;
-         VG_(fcntl)(VG_(xml_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
-      }
+      tmp_xml_fd = move_fd_into_safe_range(tmp_xml_fd, True);
    } else {
       // If they said --xml-fd=-1, don't print anything.  Plausible for use in
       // regression testing suites that use client requests to count errors.
@@ -989,9 +980,12 @@
    If logging to file or a socket, write details of parent PID and
    command line args, to help people trying to interpret the
    results of a run which encompasses multiple processes. */
-static void print_preamble ( Bool logging_to_fd, 
-                             Char* xml_fname_unexpanded,
-                             const HChar* toolname )
+// TODO(timurrrr): we add a non-static declaration of this function since
+// we need it in coregrind/m_libcproc.c
+// Should we move it to some header file?
+void print_preamble ( Bool logging_to_fd, const HChar* toolname );
+
+void print_preamble ( Bool logging_to_fd, const HChar* toolname )
 {
    Int    i;
    HChar* xpre  = VG_(clo_xml) ? "  <line>" : "";
@@ -999,9 +993,15 @@
    UInt (*umsg_or_xml)( const HChar*, ... )
       = VG_(clo_xml) ? VG_(printf_xml) : VG_(umsg);
 
+   static const char* last_toolname = NULL;
    vg_assert( VG_(args_for_client) );
    vg_assert( VG_(args_for_valgrind) );
+
+   // This way you may pass toolname == NULL provided the first invocation
+   // with toolname != NULL takes place in valgrind_main().
+   toolname = (toolname == NULL ? last_toolname : toolname);
    vg_assert( toolname );
+   last_toolname = toolname;
 
    if (VG_(clo_xml)) {
       VG_(printf_xml)("<?xml version=\"1.0\"?>\n");
@@ -1013,7 +1013,7 @@
       VG_(printf_xml)("\n");
    }
 
-   if (VG_(clo_xml) || VG_(clo_verbosity > 0)) {
+   if (VG_(clo_xml) || VG_(clo_verbosity) > 0) {
 
       if (VG_(clo_xml))
          VG_(printf_xml)("<preamble>\n");
@@ -1067,6 +1067,7 @@
    }
    else
    if (VG_(clo_xml)) {
+      Char *xml_fname_unexpanded = VG_(clo_xml_fname_unexpanded);
       VG_(printf_xml)("\n");
       VG_(printf_xml)("<pid>%d</pid>\n", VG_(getpid)());
       VG_(printf_xml)("<ppid>%d</ppid>\n", VG_(getppid)());
@@ -1374,7 +1375,6 @@
    Int     need_help          = 0; // 0 = no, 1 = --help, 2 = --help-debug
    ThreadId tid_main          = VG_INVALID_THREADID;
    Bool    logging_to_fd      = False;
-   Char* xml_fname_unexpanded = NULL;
    Int     loglevel, i;
    struct vki_rlimit zero = { 0, 0 };
    XArray* addr2dihandle = NULL;
@@ -1872,8 +1872,7 @@
    VG_(debugLog)(1, "main",
                     "(main_) Process Valgrind's command line options, "
                     "setup logging\n");
-   main_process_cmd_line_options ( &logging_to_fd, &xml_fname_unexpanded,
-                                   toolname );
+   main_process_cmd_line_options ( &logging_to_fd, toolname );
 
    //--------------------------------------------------------------
    // Zeroise the millisecond counter by doing a first read of it.
@@ -1886,10 +1885,10 @@
    //   p: tl_pre_clo_init            [for 'VG_(details).name' and friends]
    //   p: main_process_cmd_line_options()
    //         [for VG_(clo_verbosity), VG_(clo_xml),
-   //          logging_to_fd, xml_fname_unexpanded]
+   //          logging_to_fd]
    //--------------------------------------------------------------
    VG_(debugLog)(1, "main", "Print the preamble...\n");
-   print_preamble(logging_to_fd, xml_fname_unexpanded, toolname);
+   print_preamble(logging_to_fd, toolname);
    VG_(debugLog)(1, "main", "...finished the preamble\n");
 
    //--------------------------------------------------------------
Index: coregrind/m_libcproc.c
===================================================================
--- coregrind/m_libcproc.c	(revision 10880)
+++ coregrind/m_libcproc.c	(working copy)
@@ -33,9 +33,12 @@
 #include "pub_core_vkiscnums.h"
 #include "pub_core_libcbase.h"
 #include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_libcproc.h"
 #include "pub_core_libcsignal.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_options.h"
 #include "pub_core_seqmatch.h"
 #include "pub_core_mallocfree.h"
 #include "pub_core_syscall.h"
@@ -708,10 +711,39 @@
          (*atforks[i].parent)(tid);
 }
 
+// Defined in m_main.c
+void print_preamble(Bool logging_to_fd, const char* toolname);
+
+Char* VG_(clo_log_fname_unexpanded) = NULL;
+Char* VG_(clo_xml_fname_unexpanded) = NULL;
+
+// If --log-file=ABC%pXYZ is specified, we'd like to have separate log files
+// for each forked child.
+// If %p is present in the --log-file option, this function creates
+// a new log file and redirects the child's output to it.
+static void open_new_logfile_for_forked_child(void)
+{
+   Int tmp_fd = -1;
+
+   if (VG_(log_output_sink).is_socket == False && VG_(clo_log_fname_unexpanded) != NULL) {
+     tmp_fd = reopen_output_fd(False);
+     VG_(log_output_sink).fd = VG_(safe_fd)(tmp_fd);
+   }
+
+   if (VG_(xml_output_sink).is_socket == False && VG_(clo_xml_fname_unexpanded) != NULL) {
+     tmp_fd = reopen_output_fd(True);
+     VG_(xml_output_sink).fd = VG_(safe_fd)(tmp_fd);
+   }
+
+   print_preamble(False, NULL);
+}
+
 void VG_(do_atfork_child)(ThreadId tid)
 {
    Int i;
 
+   open_new_logfile_for_forked_child();
+
    for (i = 0; i < n_atfork; i++)
       if (atforks[i].child != NULL)
          (*atforks[i].child)(tid);
Index: coregrind/pub_core_options.h
===================================================================
--- coregrind/pub_core_options.h	(revision 10880)
+++ coregrind/pub_core_options.h	(working copy)
@@ -74,6 +74,9 @@
 extern Char* VG_(clo_log_fname_expanded);
 extern Char* VG_(clo_xml_fname_expanded);
 
+extern Char* VG_(clo_log_fname_unexpanded);
+extern Char* VG_(clo_xml_fname_unexpanded);
+
 /* Add timestamps to log messages?  default: NO */
 extern Bool  VG_(clo_time_stamp);