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
|
/*
* Copyright (c) 1997-2002 Silicon Graphics, Inc. All Rights Reserved.
*
* Check that file descriptors from pmNewContext are closed on an exec()
* call. If not, every open pmcd file descriptor is carried across into the
* new program and even if the new program uses libpcp, libpcp can't know what
* the file descriptors are for. In other words we leak fds across an exec().
*
* This was fixed by setting the close on exec flag in pmNewContext.
*/
#include <pcp/pmapi.h>
#include <pcp/impl.h>
#include <sys/wait.h>
void
printNextFd(void)
{
int fd;
int sts;
fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
perror("printNextFd");
exit(1);
}
printf("next free file descriptor = %d", fd);
sts = close(fd);
if (sts < 0) {
fprintf(stderr, "error closing fd = %d\n", fd);
exit(1);
}
}
int
main(int argc, char* argv[])
{
int sts;
long run;
char *endp;
int fd;
__pmSetProgname(argv[0]);
if (argc != 2) {
fprintf(stderr,
"Usage: %s count\nwhere count is the number of runs required\n",
pmProgname);
exit(1);
}
run = strtol(argv[1], &endp, 0);
if (*endp || run < 0) {
fprintf(stderr, "bad run count specified: %s\n", argv[1]);
exit(1);
}
/*
* Some stdio environments start with strange fd's open ... close
* 'em all to give us some breathing space
*/
for (fd = 3; fd < 100; fd++)
close(fd);
printf("invocation %ld: ", run);
fputs(" at startup, ", stdout);
printNextFd();
sts = pmNewContext(PM_CONTEXT_HOST, "localhost");
if (sts < 0) {
fprintf(stderr, "_pmNewContext(localhost): %s\n", pmErrStr(sts));
exit(1);
}
fputs((run > 1) ? " at exec, " : " at exit, ", stdout);
printNextFd();
fputs("\n", stdout);
if (run > 1) {
pid_t childPid;
childPid = fork();
if (childPid < 0) {
perror("fork() failed");
exit(1);
}
else if (childPid) {
int sts;
wait(&sts);
}
else {
char* childArgv[3];
int sts;
childArgv[0] = argv[0];
/* numeric arguments will get shorter, not longer so this is safe */
childArgv[1] = strdup(argv[1]);
if (childArgv[1] == NULL) {
perror("can't copy argv[1]\n");
exit(1);
}
sprintf(childArgv[1], "%ld", run - 1);
childArgv[2] = NULL;
sts = execvp(childArgv[0], childArgv);
if (sts < 0) {
perror("execvp() failed");
exit(1);
}
}
}
return 0;
}
|