Chad Mynhier
2008-Oct-02 01:24 UTC
[dtrace-discuss] Prelease() behavior (related to 6712247: dtrace -c runs the program despite errors)
Executive summary: If PR_KLC is set for a process, should Prelease() cause the process to be killed? Details: I''ve been looking at 6712247 ("dtrace -c runs the program despite errors"), and it looks like libdtrace expects Prelease() to terminate a process if PR_KLC is set. The code that shows this assumption is the following from http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libdtrace/common/dt_proc.c: 707 /* 708 * If neither PR_KLC nor PR_RLC is set, then the process is stopped by 709 * an external debugger and we were waiting in dt_proc_waitrun(). 710 * Leave the process in this condition using PRELEASE_HANG. 711 */ 712 if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) { 713 dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid); 714 rflag = PRELEASE_HANG; 715 } else { 716 dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); 717 rflag = 0; /* apply kill or run-on-last-close */ 718 } The following program demonstrates that a process with PR_KLC set won''t be killed if Prelease() is called: ------------------------------------------------------------------------ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include "libproc.h" int main(int argc, char *argv[]) { int err; pid_t pid; struct ps_prochandle *P; if (argc < 2 || (pid = (pid_t) atoi(argv[1])) == 0) { fprintf(stderr, "Need a valid pid\n"); exit(1); } if ((P = Pgrab(pid, 0, &err)) == NULL) { fprintf(stderr, "Couldn''t grab pid %d (reason %d)\n", (int) pid, err); exit(1); } if (Punsetflags(P, PR_RLC) < 0) fprintf(stderr, "Couldn''t set PR_RLC\n"); if (Psetflags(P, PR_KLC) < 0) fprintf(stderr, "Couldn''t set PR_KLC\n"); #if 0 Prelease(P, 0); #endif printf("released pid %d\n", (int) pid); } ------------------------------------------------------------------------ Without the Prelease() call, a process is killed if its pid is fed to this program. With the Prelease() call, a process continues to run. (I''ve observed what happens in prclose() when both versions of the above program are run, but I''m really asking what _should_ happen in this case. I can see what _is_ happening.) Thanks, Chad
Adam Leventhal
2008-Oct-06 05:17 UTC
[dtrace-discuss] Prelease() behavior (related to 6712247: dtrace -c runs the program despite errors)
> Without the Prelease() call, a process is killed if its pid is fed to > this program. With the Prelease() call, a process continues to run.Doing a little DTrace investigation, I see that we unset PR_KLC in Prelease() from restore_tracing_flags(). Here''s the invocation I used: # dtrace -c ''/usr/sbin/i86/dtrace -n agsajg -c date'' -n ''pid $target::P*setflags:entry{ printf("%x", arg1); }'' -Z Perhaps fixing this would be as simple as passing PRELEASE_KILL as the flag parameter to Prelease(). Adam -- Adam Leventhal, Fishworks http://blogs.sun.com/ahl
Mike Shapiro
2008-Oct-06 06:10 UTC
[dtrace-discuss] Prelease() behavior (related to 6712247: dtrace -c runs the program despite errors)
On Sun, Oct 05, 2008 at 10:17:27PM -0700, Adam Leventhal wrote:> > Without the Prelease() call, a process is killed if its pid is fed to > > this program. With the Prelease() call, a process continues to run. > > > Doing a little DTrace investigation, I see that we unset PR_KLC in > Prelease() from restore_tracing_flags(). Here''s the invocation I used: > > # dtrace -c ''/usr/sbin/i86/dtrace -n agsajg -c date'' -n ''pid > $target::P*setflags:entry{ printf("%x", arg1); }'' -Z > > Perhaps fixing this would be as simple as passing PRELEASE_KILL as the > flag parameter to Prelease(). > > AdamYes. Basically this: } else { dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); rflag = 0; /* apply kill or run-on-last-close */ } should be this: } else if (Pstatus(dpr->dpr_proc)->pr_flags & PR_KLC) { dt_dprintf("killing pid %d\n", (int)dpr->dpr_pid); rflag = PRELEASE_KILL; /* apply kill-on-last-close */ } else { dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); rflag = 0; /* apply run-on-last-close */ } The Prelease() flags are: * PRELEASE_CLEAR Clear all tracing flags. * PRELEASE_RETAIN Retain current tracing flags. * PRELEASE_HANG Leave the process stopped and abandoned. * PRELEASE_KILL Terminate the process with SIGKILL. but in the absence of those flags (0), the behavior is to restore the flags as they were found when we originally attached (that is what restore_tracing_flags() does). -Mike -- Mike Shapiro, Sun Microsystems Fishworks. blogs.sun.com/mws/
Chad Mynhier
2008-Oct-07 00:55 UTC
[dtrace-discuss] Prelease() behavior (related to 6712247: dtrace -c runs the program despite errors)
On Mon, Oct 6, 2008 at 2:10 AM, Mike Shapiro <mws at sun.com> wrote:> On Sun, Oct 05, 2008 at 10:17:27PM -0700, Adam Leventhal wrote: >> > Without the Prelease() call, a process is killed if its pid is fed to >> > this program. With the Prelease() call, a process continues to run. >> >> >> Doing a little DTrace investigation, I see that we unset PR_KLC in >> Prelease() from restore_tracing_flags(). Here''s the invocation I used: >> >> # dtrace -c ''/usr/sbin/i86/dtrace -n agsajg -c date'' -n ''pid >> $target::P*setflags:entry{ printf("%x", arg1); }'' -Z >> >> Perhaps fixing this would be as simple as passing PRELEASE_KILL as the >> flag parameter to Prelease(). >> >> Adam > > Yes. Basically this: > > } else { > dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); > rflag = 0; /* apply kill or run-on-last-close */ > } > > should be this: > > } else if (Pstatus(dpr->dpr_proc)->pr_flags & PR_KLC) { > dt_dprintf("killing pid %d\n", (int)dpr->dpr_pid); > rflag = PRELEASE_KILL; /* apply kill-on-last-close */ > } else { > dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); > rflag = 0; /* apply run-on-last-close */ > }Yep, that was what I''d originally intended to do, but the comment seemed to indicate that something else was assumed to be going on, and that something else didn''t match what I was seeing. I was wondering if the bug were here in libdtrace, or if there was an underlying bug in libproc or procfs related to Prelease(). (And it must have been a momentary bit of blindness that I didn''t notice the restore_tracing_flags() call.) Thanks, Chad