Print this page
OS-3280 need a way to specify the root of a native system in the lx brand
OS-3279 lx brand should allow delegated datasets
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/ptools/preap/preap.c
+++ new/usr/src/cmd/ptools/preap/preap.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 #include <stdio.h>
30 28 #include <stdlib.h>
31 29 #include <unistd.h>
32 30 #include <fcntl.h>
33 31 #include <ctype.h>
34 32 #include <string.h>
35 33 #include <signal.h>
36 34 #include <errno.h>
37 35 #include <sys/types.h>
38 36 #include <sys/wait.h>
39 37 #include <libproc.h>
38 +#include <limits.h>
39 +#include "ptools_common.h"
40 40
41 41 #define NOREAP_TIME 60 /* wait 60 seconds before allow a reap */
42 42
43 43 static volatile int interrupt;
44 44 static int Fflag;
45 45 static char *command;
46 46
47 47 static void
48 48 intr(int sig)
49 49 {
50 50 interrupt = sig;
51 51 }
52 52
53 53 static int
54 54 open_usage(pid_t pid, int *perr)
55 55 {
56 - char path[64];
56 + char path[PATH_MAX];
57 57 struct stat64 st;
58 58 int fd;
59 59
60 - (void) snprintf(path, sizeof (path), "/proc/%d/usage", (int)pid);
60 + (void) proc_snprintf(path, sizeof (path), "/proc/%d/usage", (int)pid);
61 61
62 62 /*
63 63 * Attempt to open the usage file, and return the fd if we can
64 64 * confirm this is a regular file provided by /proc.
65 65 */
66 66 if ((fd = open64(path, O_RDONLY)) >= 0) {
67 67 if (fstat64(fd, &st) != 0 || !S_ISREG(st.st_mode) ||
68 68 strcmp(st.st_fstype, "proc") != 0) {
69 69 (void) close(fd);
70 70 fd = -1;
71 71 }
72 72 } else if (errno == EACCES || errno == EPERM)
73 73 *perr = G_PERM;
74 74
75 75 return (fd);
76 76 }
77 77
78 78 static int
79 79 proc_usage(pid_t pid, prusage_t *pup, int *perr)
80 80 {
81 81 int fd;
82 82
83 83 *perr = G_NOPROC;
84 84
85 85 if ((fd = open_usage(pid, perr)) != -1) {
86 86 if (read(fd, pup, sizeof (prusage_t)) == sizeof (prusage_t)) {
87 87 *perr = 0;
88 88 (void) close(fd);
89 89 return (0);
90 90 }
91 91
92 92 /*
93 93 * If the read failed, the process may have gone away.
94 94 */
95 95 (void) close(fd);
96 96 }
97 97 return (-1);
98 98 }
99 99
100 100 /*
101 101 * Force the parent process (ppid) to wait for its child process (pid).
102 102 */
103 103 static int
104 104 reap(char *arg, pid_t *reap_pid, int *exit_status)
105 105 {
106 106 struct ps_prochandle *Pr;
107 107 siginfo_t siginfo;
108 108 psinfo_t psinfo;
109 109 prusage_t usage;
110 110 pid_t pid, ppid;
111 111 time_t elapsed;
112 112 int gret;
113 113
114 114 /*
115 115 * get the specified pid and the psinfo struct
116 116 */
117 117 if ((pid = proc_arg_psinfo(arg, PR_ARG_PIDS, &psinfo, &gret)) == -1) {
118 118 (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
119 119 command, arg, Pgrab_error(gret));
120 120 return (1);
121 121 }
122 122
123 123 if (psinfo.pr_nlwp != 0) {
124 124 (void) fprintf(stderr, "%s: process not defunct: %d\n",
125 125 command, (int)pid);
126 126 return (1);
127 127 }
128 128
129 129 *exit_status = psinfo.pr_wstat;
130 130 *reap_pid = psinfo.pr_pid;
131 131 ppid = psinfo.pr_ppid;
132 132
133 133 if (ppid == 1) {
134 134 (void) fprintf(stderr, "%s: Failed to reap %d: the only "
135 135 "non-defunct ancestor is 'init'\n", command,
136 136 (int)pid);
137 137 return (1);
138 138 }
139 139
140 140 if (proc_usage(pid, &usage, &gret) == 0) {
141 141 elapsed = usage.pr_tstamp.tv_sec - usage.pr_term.tv_sec;
142 142 } else {
143 143 (void) fprintf(stderr, "%s: cannot examine %d: %s\n",
144 144 command, (int)pid, Pgrab_error(gret));
145 145 return (1);
146 146 }
147 147
148 148 if ((Fflag == 0) && (elapsed < NOREAP_TIME)) {
149 149 (void) fprintf(stderr, "%s: unsafe to reap %d; it has been "
150 150 "defunct less than %d seconds\n", command, (int)pid,
151 151 NOREAP_TIME);
152 152 return (1);
153 153 }
154 154
155 155 if ((Pr = Pgrab(ppid, Fflag | PGRAB_NOSTOP, &gret)) == NULL) {
156 156 (void) fprintf(stderr, "%s: cannot examine %d: %s\n", command,
157 157 (int)ppid, Pgrab_error(gret));
158 158 return (1);
159 159 }
160 160
161 161 if ((Fflag == 0) && (Pstate(Pr) == PS_STOP)) {
162 162 Prelease(Pr, 0);
163 163 (void) fprintf(stderr, "%s: unsafe to reap %d; parent is "
164 164 "stopped and may reap status upon restart\n", command,
165 165 (int)pid);
166 166 return (1);
167 167 }
168 168
169 169 /*
170 170 * Pstop() will fail if the process to be stopped has become a zombie.
171 171 * This means that we can say with certainty that the child of this
172 172 * process has not changed parents (i.e. been reparented to init) once
173 173 * the Pstop() succeeds.
174 174 */
175 175 if (Pstop(Pr, 1000) != 0) {
176 176 Prelease(Pr, 0);
177 177 (void) fprintf(stderr, "%s: failed to stop %d: %s", command,
178 178 (int)ppid, strerror(errno));
179 179 return (1);
180 180 }
181 181
182 182 if (pr_waitid(Pr, P_PID, pid, &siginfo, WEXITED|WNOHANG) != 0) {
183 183 Prelease(Pr, 0);
184 184 (void) fprintf(stderr, "%s: waitid() in process %d failed: %s",
185 185 command, (int)ppid, strerror(errno));
186 186 return (1);
187 187 }
188 188
189 189 Prelease(Pr, 0);
190 190 return (0);
191 191 }
192 192
193 193 static void
194 194 print_exit_status(pid_t pid, int wstat)
195 195 {
196 196 (void) printf("%d: ", (int)pid);
197 197 if (WIFSIGNALED(wstat)) {
198 198 char buf[SIG2STR_MAX];
199 199 int sig = WTERMSIG(wstat);
200 200
201 201 if (sig2str(sig, buf) == 0)
202 202 (void) printf("killed by signal %s", buf);
203 203 else
204 204 (void) printf("killed by signal %d", sig);
205 205
206 206 if (WCOREDUMP(wstat))
207 207 (void) printf(" (core dumped)");
208 208 } else {
209 209 (void) printf("exited with status %d", WEXITSTATUS(wstat));
210 210 }
211 211 (void) printf("\n");
212 212 }
213 213
214 214 int
215 215 main(int argc, char *argv[])
216 216 {
217 217 int retc = 0;
218 218 int opt;
219 219 int errflg = 0;
220 220
221 221 if ((command = strrchr(argv[0], '/')) != NULL)
222 222 command++;
223 223 else
224 224 command = argv[0];
225 225
226 226 while ((opt = getopt(argc, argv, "F")) != EOF) {
227 227 switch (opt) {
228 228 case 'F': /* force grabbing (no O_EXCL) */
229 229 Fflag = PGRAB_FORCE;
230 230 break;
231 231 default:
232 232 errflg = 1;
233 233 break;
234 234 }
235 235 }
236 236
237 237 argc -= optind;
238 238 argv += optind;
239 239
240 240 if (errflg || argc <= 0) {
241 241 (void) fprintf(stderr, "usage: %s pid ...\n", command);
242 242 (void) fprintf(stderr, " (Reap a defunct process by forcing "
243 243 "its parent to wait(2) for it)\n");
244 244 exit(2);
245 245 }
246 246
247 247 /* catch signals from terminal */
248 248 if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
249 249 (void) sigset(SIGHUP, intr);
250 250 if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
251 251 (void) sigset(SIGINT, intr);
252 252 if (sigset(SIGPIPE, SIG_IGN) == SIG_DFL)
253 253 (void) sigset(SIGPIPE, intr);
254 254 if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
255 255 (void) sigset(SIGQUIT, intr);
256 256 (void) sigset(SIGTERM, intr);
257 257
258 258 while (--argc >= 0 && !interrupt) {
259 259 pid_t pid;
260 260 int wstat, r;
261 261
262 262 retc += r = reap(*argv++, &pid, &wstat);
263 263
264 264 if (r == 0)
265 265 print_exit_status(pid, wstat);
266 266 }
267 267
268 268 if (interrupt && retc == 0)
269 269 retc++;
270 270 return (retc == 0 ? 0 : 1);
271 271 }
|
↓ open down ↓ |
201 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX