blob: faf9f9cc136bc9d7cf4b1099144620cb4c67a0d8 [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*
njn9a0cba42007-04-15 22:15:57 +00002 This file is part of Callgrind, a Valgrind tool for call graph
weidendoa17f2a32006-03-20 10:27:30 +00003 profiling programs.
4
sewardj9ebd6e02007-01-08 06:01:59 +00005 Copyright (C) 2002-2007, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +00006
njn9a0cba42007-04-15 22:15:57 +00007 This tool is derived from and contains lot of code from Cachegrind
8 Copyright (C) 2002 Nicholas Nethercote (njn@valgrind.org)
weidendoa17f2a32006-03-20 10:27:30 +00009
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 02111-1307, USA.
24
25 The GNU General Public License is contained in the file COPYING.
26*/
27
28/*
29 * Functions related to interactive commands via "callgrind.cmd"
30 */
31
32#include "config.h"
33#include "global.h"
34
35#include <pub_tool_threadstate.h> // VG_N_THREADS
36
weidendo4e28a852006-04-21 00:58:58 +000037// Version for the syntax in command/result files for interactive control
38#define COMMAND_VERSION "1.0"
39
weidendoa17f2a32006-03-20 10:27:30 +000040static Char outbuf[FILENAME_LEN + FN_NAME_LEN + OBJ_NAME_LEN];
41
42static Char* command_file = 0;
43static Char* command_file2 = 0;
weidendo4e28a852006-04-21 00:58:58 +000044static Char* current_command_file = 0;
weidendoa17f2a32006-03-20 10:27:30 +000045static Char* result_file = 0;
weidendo4e28a852006-04-21 00:58:58 +000046static Char* result_file2 = 0;
47static Char* current_result_file = 0;
weidendoa17f2a32006-03-20 10:27:30 +000048static Char* info_file = 0;
49static Char* dump_base = 0;
50
weidendo4ce5e792006-09-20 21:29:39 +000051static Int thisPID = 0;
weidendoa17f2a32006-03-20 10:27:30 +000052
weidendo4ce5e792006-09-20 21:29:39 +000053/**
54 * Setup for interactive control of a callgrind run
55 */
56static void setup_control(void)
weidendoa17f2a32006-03-20 10:27:30 +000057{
weidendo4ce5e792006-09-20 21:29:39 +000058 Int fd, size;
weidendoa17f2a32006-03-20 10:27:30 +000059 SysRes res;
weidendo4ce5e792006-09-20 21:29:39 +000060 Char* dir, *dump_filename;
weidendoa17f2a32006-03-20 10:27:30 +000061
weidendo4ce5e792006-09-20 21:29:39 +000062 CLG_ASSERT(thisPID != 0);
weidendoa17f2a32006-03-20 10:27:30 +000063
weidendo4ce5e792006-09-20 21:29:39 +000064 fd = -1;
65 dir = CLG_(get_base_directory)();
66 dump_base = CLG_(get_dump_file_base)();
67
68 /* base name of dump files with PID ending */
69 size = VG_(strlen)(dump_base) + 10;
70 dump_filename = (char*) CLG_MALLOC(size);
71 CLG_ASSERT(dump_filename != 0);
72 VG_(sprintf)(dump_filename, "%s.%d", dump_base, thisPID);
73
74 /* name of command file */
weidendoa17f2a32006-03-20 10:27:30 +000075 size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_COMMANDNAME) +10;
76 command_file = (char*) CLG_MALLOC(size);
77 CLG_ASSERT(command_file != 0);
78 VG_(sprintf)(command_file, "%s/%s.%d",
weidendo4ce5e792006-09-20 21:29:39 +000079 dir, DEFAULT_COMMANDNAME, thisPID);
weidendoa17f2a32006-03-20 10:27:30 +000080
81 /* This is for compatibility with the "Force Now" Button of current
82 * KCachegrind releases, as it doesn't use ".pid" to distinguish
83 * different callgrind instances from same base directory.
weidendoa17f2a32006-03-20 10:27:30 +000084 */
85 command_file2 = (char*) CLG_MALLOC(size);
86 CLG_ASSERT(command_file2 != 0);
87 VG_(sprintf)(command_file2, "%s/%s",
88 dir, DEFAULT_COMMANDNAME);
89
90 size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_RESULTNAME) +10;
91 result_file = (char*) CLG_MALLOC(size);
92 CLG_ASSERT(result_file != 0);
93 VG_(sprintf)(result_file, "%s/%s.%d",
weidendo4ce5e792006-09-20 21:29:39 +000094 dir, DEFAULT_RESULTNAME, thisPID);
weidendoa17f2a32006-03-20 10:27:30 +000095
weidendo4e28a852006-04-21 00:58:58 +000096 /* If we get a command from a command file without .pid, use
97 * a result file without .pid suffix
98 */
99 result_file2 = (char*) CLG_MALLOC(size);
100 CLG_ASSERT(result_file2 != 0);
101 VG_(sprintf)(result_file2, "%s/%s",
102 dir, DEFAULT_RESULTNAME);
103
weidendoa17f2a32006-03-20 10:27:30 +0000104 info_file = (char*) CLG_MALLOC(VG_(strlen)(DEFAULT_INFONAME) + 10);
105 CLG_ASSERT(info_file != 0);
weidendo4ce5e792006-09-20 21:29:39 +0000106 VG_(sprintf)(info_file, "%s.%d", DEFAULT_INFONAME, thisPID);
weidendoa17f2a32006-03-20 10:27:30 +0000107
weidendo4ce5e792006-09-20 21:29:39 +0000108 CLG_DEBUG(1, "Setup for interactive control (PID: %d):\n", thisPID);
109 CLG_DEBUG(1, " dump file base: '%s'\n", dump_filename);
weidendoa17f2a32006-03-20 10:27:30 +0000110 CLG_DEBUG(1, " command file: '%s'\n", command_file);
111 CLG_DEBUG(1, " result file: '%s'\n", result_file);
112 CLG_DEBUG(1, " info file: '%s'\n", info_file);
113
114 /* create info file to indicate that we are running */
115 res = VG_(open)(info_file, VKI_O_WRONLY|VKI_O_TRUNC, 0);
116 if (res.isError) {
117 res = VG_(open)(info_file, VKI_O_CREAT|VKI_O_WRONLY,
118 VKI_S_IRUSR|VKI_S_IWUSR);
119 if (res.isError) {
120 VG_(message)(Vg_DebugMsg,
121 "warning: can't write info file '%s'", info_file);
122 info_file = 0;
123 fd = -1;
124 }
125 }
126 if (!res.isError)
sewardje8089302006-10-17 02:15:17 +0000127 fd = (Int) res.res;
weidendoa17f2a32006-03-20 10:27:30 +0000128 if (fd>=0) {
129 Char buf[512];
130 Int i;
weidendo5bd7eca2007-02-26 00:16:09 +0000131
132 WRITE_STR3(fd,
133 "# This file is generated by Callgrind-" VERSION ".\n"
134 "# It is used to enable controlling the supervision of\n"
135 "# '", VG_(args_the_exename), "'\n"
136 "# by external tools.\n\n");
weidendoa17f2a32006-03-20 10:27:30 +0000137
weidendo4e28a852006-04-21 00:58:58 +0000138 VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000139 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
140
weidendo5bd7eca2007-02-26 00:16:09 +0000141 WRITE_STR3(fd, "base: ", dir, "\n");
142 WRITE_STR3(fd, "dumps: ", dump_filename, "\n");
143 WRITE_STR3(fd, "control: ", command_file, "\n");
144 WRITE_STR3(fd, "result: ", result_file, "\n");
145
146 WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000147 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
148 HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
149 if (!arg) continue;
weidendo5bd7eca2007-02-26 00:16:09 +0000150 WRITE_STR2(fd, " ", arg);
weidendoa17f2a32006-03-20 10:27:30 +0000151 }
weidendoa17f2a32006-03-20 10:27:30 +0000152 VG_(write)(fd, "\n", 1);
153 VG_(close)(fd);
154 }
weidendo4ce5e792006-09-20 21:29:39 +0000155}
weidendoa17f2a32006-03-20 10:27:30 +0000156
weidendo4ce5e792006-09-20 21:29:39 +0000157void CLG_(init_command)()
158{
159 thisPID = VG_(getpid)();
160 setup_control();
weidendoa17f2a32006-03-20 10:27:30 +0000161}
162
163void CLG_(finish_command)()
164{
165 /* unlink info file */
166 if (info_file) VG_(unlink)(info_file);
167}
168
169
170static Int createRes(Int fd)
171{
172 SysRes res;
173
174 if (fd > -2) return fd;
175
176 /* fd == -2: No error, but we need to create the file */
weidendo4e28a852006-04-21 00:58:58 +0000177 CLG_ASSERT(current_result_file != 0);
178 res = VG_(open)(current_result_file,
weidendoa17f2a32006-03-20 10:27:30 +0000179 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
180 VKI_S_IRUSR|VKI_S_IWUSR);
181
182 /* VG_(open) can return any negative number on error. Remap errors to -1,
183 * to not confuse it with our special value -2
184 */
185 if (res.isError) fd = -1;
sewardje8089302006-10-17 02:15:17 +0000186 else fd = (Int) res.res;
weidendoa17f2a32006-03-20 10:27:30 +0000187
188 return fd;
189}
190
weidendo4e28a852006-04-21 00:58:58 +0000191/* Run Info: Persistant information of the callgrind run */
weidendoa17f2a32006-03-20 10:27:30 +0000192static Int dump_info(Int fd)
193{
194 Char* buf = outbuf;
195 int i;
196
197 if ( (fd = createRes(fd)) <0) return fd;
198
weidendo4e28a852006-04-21 00:58:58 +0000199 /* creator */
200 VG_(sprintf)(buf, "creator: callgrind-" VERSION "\n");
201 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
202
weidendoa17f2a32006-03-20 10:27:30 +0000203 /* version */
weidendo4e28a852006-04-21 00:58:58 +0000204 VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000205 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
206
207 /* "pid:" line */
208 VG_(sprintf)(buf, "pid: %d\n", VG_(getpid)());
209 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
210
211 /* "base:" line */
weidendo5bd7eca2007-02-26 00:16:09 +0000212 WRITE_STR3(fd, "base: ", dump_base, "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000213
214 /* "cmd:" line */
weidendo5bd7eca2007-02-26 00:16:09 +0000215 WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000216 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
217 HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
218 if (!arg) continue;
weidendo5bd7eca2007-02-26 00:16:09 +0000219 WRITE_STR2(fd, " ", arg);
weidendoa17f2a32006-03-20 10:27:30 +0000220 }
weidendo4e28a852006-04-21 00:58:58 +0000221 VG_(write)(fd, "\n", 1);
weidendoa17f2a32006-03-20 10:27:30 +0000222
223 return fd;
224}
225
226
227/* Helper for dump_state */
228
229Int dump_fd;
230
231void static dump_state_of_thread(thread_info* ti)
232{
233 Char* buf = outbuf;
234 int t = CLG_(current_tid);
235 Int p, i;
236 static FullCost sum = 0, tmp = 0;
237 BBCC *from, *to;
238 call_entry* ce;
239
240 p = VG_(sprintf)(buf, "events-%d: ", t);
241 CLG_(init_cost_lz)( CLG_(sets).full, &sum );
242 CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
243 CLG_(add_diff_cost)( CLG_(sets).full, sum,
244 ti->lastdump_cost,
245 ti->states.entry[0]->cost);
246 CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
247 p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum);
248 p += VG_(sprintf)(buf+p, "\n");
249 VG_(write)(dump_fd, (void*)buf, p);
250
251 p = VG_(sprintf)(buf, "frames-%d: %d\n", t,
252 CLG_(current_call_stack).sp);
253 VG_(write)(dump_fd, (void*)buf, p);
254 ce = 0;
255 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
256 ce = CLG_(get_call_entry)(i);
257 /* if this frame is skipped, we don't have counters */
258 if (!ce->jcc) continue;
259
260 from = ce->jcc->from;
261 p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
262 from->cxt->fn[0]->name);
263 VG_(write)(dump_fd, (void*)buf, p);
264
265 p = VG_(sprintf)(buf, "calls-%d-%d: ",t, i);
266 p+= VG_(sprintf)(buf+p, "%llu\n", ce->jcc->call_counter);
267 VG_(write)(dump_fd, (void*)buf, p);
268
269 /* FIXME: EventSets! */
270 CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
271 CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
272 CLG_(add_diff_cost)( CLG_(sets).full, sum,
273 ce->enter_cost, CLG_(current_state).cost );
274 CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
275
276 p = VG_(sprintf)(buf, "events-%d-%d: ",t, i);
277 p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum );
278 p += VG_(sprintf)(buf+p, "\n");
279 VG_(write)(dump_fd, (void*)buf, p);
280 }
281 if (ce && ce->jcc) {
282 to = ce->jcc->to;
283 p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
284 to->cxt->fn[0]->name );
285 VG_(write)(dump_fd, (void*)buf, p);
286 }
287}
288
289/* Dump info on current callgrind state */
290static Int dump_state(Int fd)
291{
292 Char* buf = outbuf;
293 thread_info** th;
294 int t, p;
295 Int orig_tid = CLG_(current_tid);
296
297 if ( (fd = createRes(fd)) <0) return fd;
298
299 VG_(sprintf)(buf, "instrumentation: %s\n",
300 CLG_(instrument_state) ? "on":"off");
301 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
302
303 if (!CLG_(instrument_state)) return fd;
304
305 VG_(sprintf)(buf, "executed-bbs: %llu\n", CLG_(stat).bb_executions);
306 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
307
308 VG_(sprintf)(buf, "executed-calls: %llu\n", CLG_(stat).call_counter);
309 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
310
311 VG_(sprintf)(buf, "distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
312 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
313
314 VG_(sprintf)(buf, "distinct-calls: %d\n", CLG_(stat).distinct_jccs);
315 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
316
317 VG_(sprintf)(buf, "distinct-functions: %d\n", CLG_(stat).distinct_fns);
318 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
319
320 VG_(sprintf)(buf, "distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
321 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
322
323 /* "events:" line. Given here because it will be dynamic in the future */
324 p = VG_(sprintf)(buf, "events: ");
325 CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap));
326 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
327 VG_(write)(fd, "\n", 1);
328
329 /* "part:" line (number of last part. Is 0 at start */
330 VG_(sprintf)(buf, "\npart: %d\n", CLG_(get_dump_counter)());
331 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
332
333 /* threads */
334 th = CLG_(get_threads)();
335 p = VG_(sprintf)(buf, "threads:");
336 for(t=1;t<VG_N_THREADS;t++) {
337 if (!th[t]) continue;
338 p += VG_(sprintf)(buf+p, " %d", t);
339 }
340 p += VG_(sprintf)(buf+p, "\n");
341 VG_(write)(fd, (void*)buf, p);
342
343 VG_(sprintf)(buf, "current-tid: %d\n", orig_tid);
344 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
345
346 /* current event counters */
347 dump_fd = fd;
348 CLG_(forall_threads)(dump_state_of_thread);
349
350 return fd;
351}
352
353void CLG_(check_command)()
354{
355 /* check for dumps needed */
356 static Char buf[512];
357 static Char cmdBuffer[512];
358 Char *cmdPos = 0, *cmdNextLine = 0;
359 Int fd, bytesRead = 0, do_kill = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000360 SysRes res;
weidendo4ce5e792006-09-20 21:29:39 +0000361 Int currentPID;
362 static Int check_counter = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000363
weidendo4ce5e792006-09-20 21:29:39 +0000364 /* Check for PID change, i.e. whether we run as child after a fork.
365 * If yes, we setup interactive control for the new process
366 */
367 currentPID = VG_(getpid)();
368 if (thisPID != currentPID) {
369 thisPID = currentPID;
370 setup_control();
371 }
weidendoa17f2a32006-03-20 10:27:30 +0000372
weidendo4ce5e792006-09-20 21:29:39 +0000373 /* Toggle between 2 command files, with/without ".pid" postfix
374 * (needed for compatibility with KCachegrind, which wants to trigger
375 * a dump by writing into a command file without the ".pid" postfix)
376 */
377 check_counter++;
378 if (check_counter % 2) {
379 current_command_file = command_file;
380 current_result_file = result_file;
381 }
382 else {
383 current_command_file = command_file2;
384 current_result_file = result_file2;
385 }
weidendoa17f2a32006-03-20 10:27:30 +0000386
weidendo4e28a852006-04-21 00:58:58 +0000387 res = VG_(open)(current_command_file, VKI_O_RDONLY,0);
weidendoa17f2a32006-03-20 10:27:30 +0000388 if (!res.isError) {
sewardje8089302006-10-17 02:15:17 +0000389 fd = (Int) res.res;
weidendoa17f2a32006-03-20 10:27:30 +0000390 bytesRead = VG_(read)(fd,cmdBuffer,500);
391 cmdBuffer[500] = 0; /* no command overrun please */
392 VG_(close)(fd);
393 /* don't delete command file on read error (e.g. EAGAIN) */
394 if (bytesRead>0) {
395 cmdPos = cmdBuffer;
396 }
397 }
398
399 /* force creation of result file if needed */
400 fd = -2;
401
402 while((bytesRead>0) && *cmdPos) {
403
404 /* Calculate pointer for next line */
405 cmdNextLine = cmdPos+1;
406 while((bytesRead>0) && *cmdNextLine && (*cmdNextLine != '\n')) {
407 cmdNextLine++;
408 bytesRead--;
409 }
410 if ((bytesRead>0) && (*cmdNextLine == '\n')) {
411 *cmdNextLine = 0;
412 cmdNextLine++;
413 bytesRead--;
414 }
415
416 /* Command with integer option */
417 if ((*cmdPos >= '0') && (*cmdPos <='9')) {
418 int value = *cmdPos-'0';
419 cmdPos++;
420 while((*cmdPos >= '0') && (*cmdPos <='9')) {
421 value = 10*value + (*cmdPos-'0');
422 cmdPos++;
423 }
424 while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
425
426 switch(*cmdPos) {
427#if CLG_ENABLE_DEBUG
428 /* verbosity */
429 case 'V':
430 case 'v':
431 CLG_(clo).verbose = value;
432 break;
433#endif
434 default:
435 break;
436 }
437
438 cmdPos = cmdNextLine;
439 continue;
440 }
441
442 /* Command with boolean/switch option */
443 if ((*cmdPos=='+') ||
444 (*cmdPos=='-')) {
445 int value = (cmdPos[0] == '+');
446 cmdPos++;
447 while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
448
449 switch(*cmdPos) {
450 case 'I':
451 case 'i':
452 CLG_(set_instrument_state)("Command", value);
453 break;
454
455 default:
456 break;
457 }
458
459 cmdPos = cmdNextLine;
460 continue;
461 }
462
463 /* regular command */
464 switch(*cmdPos) {
465 case 'D':
466 case 'd':
467 /* DUMP */
468
469 /* skip command */
470 while(*cmdPos && (*cmdPos != ' ')) cmdPos++;
471 if (*cmdPos)
472 VG_(sprintf)(buf, "Dump Command:%s", cmdPos);
473 else
474 VG_(sprintf)(buf, "Dump Command");
475 CLG_(dump_profile)(buf, False);
476 break;
477
478 case 'Z':
479 case 'z':
480 CLG_(zero_all_cost)(False);
481 break;
482
483 case 'K':
484 case 'k':
485 /* Kill: Delay to be able to remove command file before. */
486 do_kill = 1;
487 break;
488
489 case 'I':
490 case 'i':
491 fd = dump_info(fd);
492 break;
493
494 case 's':
495 case 'S':
496 fd = dump_state(fd);
497 break;
498
499 case 'O':
500 case 'o':
501 /* Options Info */
502 if ( (fd = createRes(fd)) <0) break;
503
504 VG_(sprintf)(buf, "\ndesc: Option: --skip-plt=%s\n",
505 CLG_(clo).skip_plt ? "yes" : "no");
506 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
507 VG_(sprintf)(buf, "desc: Option: --collect-jumps=%s\n",
508 CLG_(clo).collect_jumps ? "yes" : "no");
509 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
510 VG_(sprintf)(buf, "desc: Option: --separate-recs=%d\n",
511 CLG_(clo).separate_recursions);
512 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
513 VG_(sprintf)(buf, "desc: Option: --separate-callers=%d\n",
514 CLG_(clo).separate_callers);
515 VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
516
517 break;
518
519 default:
520 break;
521 }
522
523 cmdPos = cmdNextLine;
524 }
525
526 /* If command executed, delete command file */
weidendo4e28a852006-04-21 00:58:58 +0000527 if (cmdPos) VG_(unlink)(current_command_file);
weidendoa17f2a32006-03-20 10:27:30 +0000528 if (fd>=0) VG_(close)(fd);
529
530 if (do_kill) {
531 VG_(message)(Vg_UserMsg,
weidendo4e28a852006-04-21 00:58:58 +0000532 "Killed because of command from %s", current_command_file);
weidendoa17f2a32006-03-20 10:27:30 +0000533 CLG_(fini)(0);
534 VG_(exit)(1);
535 }
536}