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 #include <stdio.h> 27 #include <stdlib.h> 28 #include <unistd.h> 29 #include <fcntl.h> 30 #include <string.h> 31 #include <errno.h> 32 #include <sys/types.h> 33 #include <signal.h> 34 #include <libproc.h> 35 36 static int start(char *); 37 static int lwpstart(int *, const lwpstatus_t *, const lwpsinfo_t *); 38 39 static char *command; 40 static const char *lwps; 41 static struct ps_prochandle *P; 42 43 int 44 main(int argc, char **argv) 45 { 46 int rc = 0; 47 48 if ((command = strrchr(argv[0], '/')) != NULL) 49 command++; 50 else 51 command = argv[0]; 52 53 if (argc <= 1) { 54 (void) fprintf(stderr, "usage:\t%s pid[/lwps] ...\n", command); 55 (void) fprintf(stderr, " (set stopped processes or lwps " 56 "running)\n"); 57 return (2); 58 } 59 60 while (--argc > 0) 61 rc += start(*++argv); 62 63 return (rc); 64 } 65 66 static int 67 start(char *arg) 68 { 69 int gcode; 70 int rc = 0; 71 72 if ((P = proc_arg_xgrab(arg, NULL, PR_ARG_PIDS, PGRAB_FORCE | 73 PGRAB_RETAIN | PGRAB_NOSTOP, &gcode, &lwps)) == NULL) { 74 (void) fprintf(stderr, "%s: cannot control %s: %s\n", 75 command, arg, Pgrab_error(gcode)); 76 return (1); 77 } 78 79 /* 80 * If the victim is stopped because of a job control signal, we 81 * need to send it SIGCONT to get it moving again, otherwise 82 * the agent will not be able to run, and so will not be able to 83 * exit the process. 84 */ 85 (void) kill(Pstatus(P)->pr_pid, SIGCONT); 86 87 /* 88 * if the agent already exists, Pcreate_agent will adopt the 89 * extant agent so that we can destroy it 90 */ 91 if (Pstatus(P)->pr_lwp.pr_flags & PR_AGENT) { 92 if (Pcreate_agent(P) != 0) { 93 (void) fprintf(stderr, 94 "%s: cannot remove agent from %s: %s\n", 95 command, arg, strerror(errno)); 96 97 Prelease(P, 0); 98 return (1); 99 } 100 101 Pdestroy_agent(P); 102 } 103 104 if (lwps != NULL) { 105 /* 106 * The user provided an lwp specification. Let's consider the 107 * lwp specification as a mask. We iterate over all lwps in the 108 * process and set running every lwp, which matches the mask. 109 * If there is no lwp matching the mask or an error occured 110 * during the iteration, set the return code to 1 as indication 111 * of an error. We need to unset run-on-last-close flag, 112 * otherwise *all* lwps could be set running after detaching 113 * from the process and not only lwps, which were selected. 114 */ 115 int lwpcount = 0; 116 117 (void) Punsetflags(P, PR_RLC); 118 (void) Plwp_iter_all(P, (proc_lwp_all_f *)lwpstart, &lwpcount); 119 120 if (lwpcount == 0) { 121 (void) fprintf(stderr, "%s: cannot control %s:" 122 " no matching LWPs found\n", command, arg); 123 rc = 1; 124 } else if (lwpcount == -1) 125 rc = 1; 126 } else { 127 (void) Psetrun(P, 0, 0); /* Set the process running. */ 128 } 129 130 /* 131 * Prelease could change the tracing flags or leave the victim hung 132 * so we free the handle by hand. 133 */ 134 Pfree(P); 135 return (rc); 136 } 137 138 /* ARGSUSED */ 139 static int 140 lwpstart(int *lwpcount, const lwpstatus_t *status, const lwpsinfo_t *info) 141 { 142 struct ps_lwphandle *L; 143 int gcode; 144 145 if (proc_lwp_in_set(lwps, info->pr_lwpid)) { 146 /* 147 * There is a race between the callback from the iterator and 148 * grabbing of the lwp. If the lwp has already exited, Lgrab 149 * will return the error code G_NOPROC. It's not a real error, 150 * only if there is no lwp matching the specification. 151 */ 152 if ((L = Lgrab(P, info->pr_lwpid, &gcode)) != NULL) { 153 (void) Lsetrun(L, 0, 0); 154 Lfree(L); 155 if (*lwpcount >= 0) 156 (*lwpcount)++; 157 } else if (gcode != G_NOPROC) { 158 (void) fprintf(stderr, "%s: cannot control %d/%d: %s\n", 159 command, (int)Pstatus(P)->pr_pid, 160 (int)info->pr_lwpid, Lgrab_error(gcode)); 161 *lwpcount = -1; 162 } 163 } 164 return (0); 165 } 166