1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <fcntl.h> 32 #include <string.h> 33 #include <errno.h> 34 #include <sys/types.h> 35 #include <signal.h> 36 #include <libproc.h> 37 38 static int start(char *); 39 static int lwpstart(int *, const lwpstatus_t *, const lwpsinfo_t *); 40 41 static char *command; 42 static const char *lwps; 43 static struct ps_prochandle *P; 44 45 int 46 main(int argc, char **argv) 47 { 48 int rc = 0; 49 50 if ((command = strrchr(argv[0], '/')) != NULL) 51 command++; 52 else 53 command = argv[0]; 54 55 if (argc <= 1) { 56 (void) fprintf(stderr, "usage:\t%s pid[/lwps] ...\n", command); 57 (void) fprintf(stderr, " (set stopped processes or lwps " 58 "running)\n"); 59 return (2); 60 } 61 62 while (--argc > 0) 63 rc += start(*++argv); 64 65 return (rc); 66 } 67 68 static int 69 start(char *arg) 70 { 71 int gcode; 72 int rc = 0; 73 74 if ((P = proc_arg_xgrab(arg, NULL, PR_ARG_PIDS, PGRAB_FORCE | 75 PGRAB_RETAIN | PGRAB_NOSTOP, &gcode, &lwps)) == NULL) { 76 (void) fprintf(stderr, "%s: cannot control %s: %s\n", 77 command, arg, Pgrab_error(gcode)); 78 return (1); 79 } 80 81 /* 82 * If the victim is stopped because of a job control signal, we 83 * need to send it SIGCONT to get it moving again, otherwise 84 * the agent will not be able to run, and so will not be able to 85 * exit the process. 86 */ 87 (void) kill(Pstatus(P)->pr_pid, SIGCONT); 88 89 /* 90 * if the agent already exists, Pcreate_agent will adopt the 91 * extant agent so that we can destroy it 92 */ 93 if (Pstatus(P)->pr_lwp.pr_flags & PR_AGENT) { 94 if (Pcreate_agent(P) != 0) { 95 (void) fprintf(stderr, 96 "%s: cannot remove agent from %s: %s\n", 97 command, arg, strerror(errno)); 98 99 Prelease(P, 0); 100 return (1); 101 } 102 103 Pdestroy_agent(P); 104 } 105 106 if (lwps != NULL) { 107 /* 108 * The user provided an lwp specification. Let's consider the 109 * lwp specification as a mask. We iterate over all lwps in the 110 * process and set running every lwp, which matches the mask. 111 * If there is no lwp matching the mask or an error occured 112 * during the iteration, set the return code to 1 as indication 113 * of an error. We need to unset run-on-last-close flag, 114 * otherwise *all* lwps could be set running after detaching 115 * from the process and not only lwps, which were selected. 116 */ 117 int lwpcount = 0; 118 119 (void) Punsetflags(P, PR_RLC); 120 (void) Plwp_iter_all(P, (proc_lwp_all_f *)lwpstart, &lwpcount); 121 122 if (lwpcount == 0) { 123 (void) fprintf(stderr, "%s: cannot control %s:" 124 " no matching LWPs found\n", command, arg); 125 rc = 1; 126 } else if (lwpcount == -1) 127 rc = 1; 128 } else { 129 (void) Psetrun(P, 0, 0); /* Set the process running. */ 130 } 131 132 /* 133 * Prelease could change the tracing flags or leave the victim hung 134 * so we free the handle by hand. 135 */ 136 Pfree(P); 137 return (rc); 138 } 139 140 /* ARGSUSED */ 141 static int 142 lwpstart(int *lwpcount, const lwpstatus_t *status, const lwpsinfo_t *info) 143 { 144 struct ps_lwphandle *L; 145 int gcode; 146 147 if (proc_lwp_in_set(lwps, info->pr_lwpid)) { 148 /* 149 * There is a race between the callback from the iterator and 150 * grabbing of the lwp. If the lwp has already exited, Lgrab 151 * will return the error code G_NOPROC. It's not a real error, 152 * only if there is no lwp matching the specification. 153 */ 154 if ((L = Lgrab(P, info->pr_lwpid, &gcode)) != NULL) { 155 (void) Lsetrun(L, 0, 0); 156 Lfree(L); 157 if (*lwpcount >= 0) 158 (*lwpcount)++; 159 } else if (gcode != G_NOPROC) { 160 (void) fprintf(stderr, "%s: cannot control %d/%d: %s\n", 161 command, (int)Pstatus(P)->pr_pid, 162 (int)info->pr_lwpid, Lgrab_error(gcode)); 163 *lwpcount = -1; 164 } 165 } 166 return (0); 167 } 168