⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcontrol.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (P->core->core_priv != NULL) {		size = MIN(P->core->core_priv_size, size);		(void) memcpy(pprv, P->core->core_priv, size);		return (size);	}	errno = ENODATA;	return (-1);}intPsetpriv(struct ps_prochandle *P, prpriv_t *pprv){	int rc;	long *ctl;	size_t sz;	if (P->state == PS_DEAD) {		errno = EBADF;		return (-1);	}	sz = PRIV_PRPRIV_SIZE(pprv) + sizeof (long);	sz = ((sz - 1) / sizeof (long) + 1) * sizeof (long);	ctl = malloc(sz);	if (ctl == NULL)		return (-1);	ctl[0] = PCSPRIV;	(void) memcpy(&ctl[1], pprv, PRIV_PRPRIV_SIZE(pprv));	if (write(P->ctlfd, ctl, sz) != sz)		rc = -1;	else		rc = 0;	free(ctl);	return (rc);}void *Pprivinfo(struct ps_prochandle *P){	/* Use default from libc */	if (P->state != PS_DEAD)		return (NULL);	return (P->core->core_privinfo);}/* * Ensure that all cached state is written to the process. * The cached state is the LWP's signal mask and registers * and the process's tracing flags. */voidPsync(struct ps_prochandle *P){	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;	long cmd[6];	iovec_t iov[12];	int n = 0;	if (P->flags & SETHOLD) {		cmd[0] = PCSHOLD;		iov[n].iov_base = (caddr_t)&cmd[0];		iov[n++].iov_len = sizeof (long);		iov[n].iov_base = (caddr_t)&P->status.pr_lwp.pr_lwphold;		iov[n++].iov_len = sizeof (P->status.pr_lwp.pr_lwphold);	}	if (P->flags & SETREGS) {		cmd[1] = PCSREG;#ifdef __i386		/* XX64 we should probably restore REG_GS after this */		if (ctlfd == P->agentctlfd)			P->status.pr_lwp.pr_reg[GS] = 0;#elif defined(__amd64)		/* XX64 */#endif		iov[n].iov_base = (caddr_t)&cmd[1];		iov[n++].iov_len = sizeof (long);		iov[n].iov_base = (caddr_t)&P->status.pr_lwp.pr_reg[0];		iov[n++].iov_len = sizeof (P->status.pr_lwp.pr_reg);	}	if (P->flags & SETSIG) {		cmd[2] = PCSTRACE;		iov[n].iov_base = (caddr_t)&cmd[2];		iov[n++].iov_len = sizeof (long);		iov[n].iov_base = (caddr_t)&P->status.pr_sigtrace;		iov[n++].iov_len = sizeof (P->status.pr_sigtrace);	}	if (P->flags & SETFAULT) {		cmd[3] = PCSFAULT;		iov[n].iov_base = (caddr_t)&cmd[3];		iov[n++].iov_len = sizeof (long);		iov[n].iov_base = (caddr_t)&P->status.pr_flttrace;		iov[n++].iov_len = sizeof (P->status.pr_flttrace);	}	if (P->flags & SETENTRY) {		cmd[4] = PCSENTRY;		iov[n].iov_base = (caddr_t)&cmd[4];		iov[n++].iov_len = sizeof (long);		iov[n].iov_base = (caddr_t)&P->status.pr_sysentry;		iov[n++].iov_len = sizeof (P->status.pr_sysentry);	}	if (P->flags & SETEXIT) {		cmd[5] = PCSEXIT;		iov[n].iov_base = (caddr_t)&cmd[5];		iov[n++].iov_len = sizeof (long);		iov[n].iov_base = (caddr_t)&P->status.pr_sysexit;		iov[n++].iov_len = sizeof (P->status.pr_sysexit);	}	if (n == 0 || writev(ctlfd, iov, n) < 0)		return;		/* nothing to do or write failed */	P->flags &= ~(SETSIG|SETFAULT|SETENTRY|SETEXIT|SETHOLD|SETREGS);}/* * Reopen the /proc file (after PS_LOST). */intPreopen(struct ps_prochandle *P){	int fd;	char procname[100];	char *fname;	if (P->state == PS_DEAD || P->state == PS_IDLE)		return (0);	if (P->agentcnt > 0) {		P->agentcnt = 1;		Pdestroy_agent(P);	}	(void) sprintf(procname, "/proc/%d/", (int)P->pid);	fname = procname + strlen(procname);	(void) strcpy(fname, "as");	if ((fd = open(procname, O_RDWR)) < 0 ||	    close(P->asfd) < 0 ||	    (fd = dupfd(fd, P->asfd)) != P->asfd) {		dprintf("Preopen: failed to open %s: %s\n",		    procname, strerror(errno));		if (fd >= 0)			(void) close(fd);		return (-1);	}	P->asfd = fd;	(void) strcpy(fname, "status");	if ((fd = open(procname, O_RDONLY)) < 0 ||	    close(P->statfd) < 0 ||	    (fd = dupfd(fd, P->statfd)) != P->statfd) {		dprintf("Preopen: failed to open %s: %s\n",		    procname, strerror(errno));		if (fd >= 0)			(void) close(fd);		return (-1);	}	P->statfd = fd;	(void) strcpy(fname, "ctl");	if ((fd = open(procname, O_WRONLY)) < 0 ||	    close(P->ctlfd) < 0 ||	    (fd = dupfd(fd, P->ctlfd)) != P->ctlfd) {		dprintf("Preopen: failed to open %s: %s\n",		    procname, strerror(errno));		if (fd >= 0)			(void) close(fd);		return (-1);	}	P->ctlfd = fd;	/*	 * Set the state to PS_RUN and wait for the process to stop so that	 * we re-read the status from the new P->statfd.  If this fails, Pwait	 * will reset the state to PS_LOST and we fail the reopen.  Before	 * returning, we also forge a bit of P->status to allow the debugger to	 * see that we are PS_LOST following a successful exec.	 */	P->state = PS_RUN;	if (Pwait(P, 0) == -1) {#ifdef _ILP32		if (errno == EOVERFLOW)			P->status.pr_dmodel = PR_MODEL_LP64;#endif		P->status.pr_lwp.pr_why = PR_SYSEXIT;		P->status.pr_lwp.pr_what = SYS_execve;		P->status.pr_lwp.pr_errno = 0;		return (-1);	}	/*	 * The process should be stopped on exec (REQUESTED)	 * or else should be stopped on exit from exec() (SYSEXIT)	 */	if (P->state == PS_STOP &&	    (P->status.pr_lwp.pr_why == PR_REQUESTED ||	    (P->status.pr_lwp.pr_why == PR_SYSEXIT &&	    (P->status.pr_lwp.pr_what == SYS_exec ||	    P->status.pr_lwp.pr_what == SYS_execve)))) {		/* fake up stop-on-exit-from-execve */		if (P->status.pr_lwp.pr_why == PR_REQUESTED) {			P->status.pr_lwp.pr_why = PR_SYSEXIT;			P->status.pr_lwp.pr_what = SYS_execve;			P->status.pr_lwp.pr_errno = 0;		}	} else {		dprintf("Preopen: expected REQUESTED or "		    "SYSEXIT(SYS_execve) stop\n");	}	return (0);}/* * Define all settable flags other than the microstate accounting flags. */#define	ALL_SETTABLE_FLAGS (PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_PTRACE)/* * Restore /proc tracing flags to their original values * in preparation for releasing the process. * Also called by Pcreate() to clear all tracing flags. */static voidrestore_tracing_flags(struct ps_prochandle *P){	long flags;	long cmd[4];	iovec_t iov[8];	if (P->flags & CREATED) {		/* we created this process; clear all tracing flags */		premptyset(&P->status.pr_sigtrace);		premptyset(&P->status.pr_flttrace);		premptyset(&P->status.pr_sysentry);		premptyset(&P->status.pr_sysexit);		if ((P->status.pr_flags & ALL_SETTABLE_FLAGS) != 0)			(void) Punsetflags(P, ALL_SETTABLE_FLAGS);	} else {		/* we grabbed the process; restore its tracing flags */		P->status.pr_sigtrace = P->orig_status.pr_sigtrace;		P->status.pr_flttrace = P->orig_status.pr_flttrace;		P->status.pr_sysentry = P->orig_status.pr_sysentry;		P->status.pr_sysexit  = P->orig_status.pr_sysexit;		if ((P->status.pr_flags & ALL_SETTABLE_FLAGS) !=		    (flags = (P->orig_status.pr_flags & ALL_SETTABLE_FLAGS))) {			(void) Punsetflags(P, ALL_SETTABLE_FLAGS);			if (flags)				(void) Psetflags(P, flags);		}	}	cmd[0] = PCSTRACE;	iov[0].iov_base = (caddr_t)&cmd[0];	iov[0].iov_len = sizeof (long);	iov[1].iov_base = (caddr_t)&P->status.pr_sigtrace;	iov[1].iov_len = sizeof (P->status.pr_sigtrace);	cmd[1] = PCSFAULT;	iov[2].iov_base = (caddr_t)&cmd[1];	iov[2].iov_len = sizeof (long);	iov[3].iov_base = (caddr_t)&P->status.pr_flttrace;	iov[3].iov_len = sizeof (P->status.pr_flttrace);	cmd[2] = PCSENTRY;	iov[4].iov_base = (caddr_t)&cmd[2];	iov[4].iov_len = sizeof (long);	iov[5].iov_base = (caddr_t)&P->status.pr_sysentry;	iov[5].iov_len = sizeof (P->status.pr_sysentry);	cmd[3] = PCSEXIT;	iov[6].iov_base = (caddr_t)&cmd[3];	iov[6].iov_len = sizeof (long);	iov[7].iov_base = (caddr_t)&P->status.pr_sysexit;	iov[7].iov_len = sizeof (P->status.pr_sysexit);	(void) writev(P->ctlfd, iov, 8);	P->flags &= ~(SETSIG|SETFAULT|SETENTRY|SETEXIT);}/* * Release the process.  Frees the process control structure. * flags: *	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. */voidPrelease(struct ps_prochandle *P, int flags){	if (P->state == PS_DEAD) {		dprintf("Prelease: releasing handle %p PS_DEAD of pid %d\n",		    (void *)P, (int)P->pid);		Pfree(P);		return;	}	if (P->state == PS_IDLE) {		file_info_t *fptr = list_next(&P->file_head);		dprintf("Prelease: releasing handle %p PS_IDLE of file %s\n",		    (void *)P, fptr->file_pname);		Pfree(P);		return;	}	dprintf("Prelease: releasing handle %p pid %d\n",	    (void *)P, (int)P->pid);	if (P->ctlfd == -1) {		Pfree(P);		return;	}	if (P->agentcnt > 0) {		P->agentcnt = 1;		Pdestroy_agent(P);	}	/*	 * Attempt to stop the process.	 */	P->state = PS_RUN;	(void) Pstop(P, 1000);	if (flags & PRELEASE_KILL) {		if (P->state == PS_STOP)			(void) Psetrun(P, SIGKILL, 0);		(void) kill(P->pid, SIGKILL);		Pfree(P);		return;	}	/*	 * If we lost control, all we can do now is close the files.	 * In this case, the last close sets the process running.	 */	if (P->state != PS_STOP &&	    (P->status.pr_lwp.pr_flags & (PR_ISTOP|PR_DSTOP)) == 0) {		Pfree(P);		return;	}	/*	 * We didn't lose control; we do more.	 */	Psync(P);	if (flags & PRELEASE_CLEAR)		P->flags |= CREATED;	if (!(flags & PRELEASE_RETAIN))		restore_tracing_flags(P);	if (flags & PRELEASE_HANG) {		/* Leave the process stopped and abandoned */		(void) Punsetflags(P, PR_RLC|PR_KLC);		Pfree(P);		return;	}	/*	 * Set the process running if we created it or if it was	 * not originally stopped or directed to stop via /proc	 * or if we were given the PRELEASE_CLEAR flag.	 */	if ((P->flags & CREATED) ||	    (P->orig_status.pr_lwp.pr_flags & (PR_ISTOP|PR_DSTOP)) == 0) {		(void) Psetflags(P, PR_RLC);		/*		 * We do this repeatedly because the process may have		 * more than one LWP stopped on an event of interest.		 * This makes sure all of them are set running.		 */		do {			if (Psetrun(P, 0, 0) == -1 && errno == EBUSY)				break; /* Agent LWP may be stuck */		} while (Pstopstatus(P, PCNULL, 0) == 0 &&		    P->status.pr_lwp.pr_flags & (PR_ISTOP|PR_DSTOP));		if (P->status.pr_lwp.pr_flags & (PR_ISTOP|PR_DSTOP))			dprintf("Prelease: failed to set process running\n");	}	Pfree(P);}/* debugging */voidprldump(const char *caller, lwpstatus_t *lsp){	char name[32];	uint32_t bits;	switch (lsp->pr_why) {	case PR_REQUESTED:		dprintf("%s: REQUESTED\n", caller);		break;	case PR_SIGNALLED:		dprintf("%s: SIGNALLED %s\n", caller,			proc_signame(lsp->pr_what, name, sizeof (name)));		break;	case PR_FAULTED:		dprintf("%s: FAULTED %s\n", caller,			proc_fltname(lsp->pr_what, name, sizeof (name)));		break;	case PR_SYSENTRY:		dprintf("%s: SYSENTRY %s\n", caller,			proc_sysname(lsp->pr_what, name, sizeof (name)));		break;	case PR_SYSEXIT:		dprintf("%s: SYSEXIT %s\n", caller,			proc_sysname(lsp->pr_what, name, sizeof (name)));		break;	case PR_JOBCONTROL:		dprintf("%s: JOBCONTROL %s\n", caller,			proc_signame(lsp->pr_what, name, sizeof (name)));		break;	case PR_SUSPENDED:		dprintf("%s: SUSPENDED\n", caller);		break;	default:		dprintf("%s: Unknown\n", caller);		break;	}	if (lsp->pr_cursig)		dprintf("%s: p_cursig  = %d\n", caller, lsp->pr_cursig);	bits = *((uint32_t *)&lsp->pr_lwppend);	if (bits)		dprintf("%s: pr_lwppend = 0x%.8X\n", caller, bits);}/* debugging */static voidprdump(struct ps_prochandle *P){	uint32_t bits;	prldump("Pstopstatus", &P->status.pr_lwp);	bits = *((uint32_t *)&P->status.pr_sigpend);	if (bits)		dprintf("Pstopstatus: pr_sigpend = 0x%.8X\n", bits);}/* * Wait for the specified process to stop or terminate. * Or, just get the current status (PCNULL). * Or, direct it to stop and get the current status (PCDSTOP). * If the agent LWP exists, do these things to the agent, * else do these things to the process as a whole. */intPstopstatus(struct ps_prochandle *P,	long request,		/* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */	uint_t msec)		/* if non-zero, timeout in milliseconds */{	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;	long ctl[3];	ssize_t rc;	int err;	int old_state = P->state;	switch (P->state) {	case PS_RUN:		break;	case PS_STOP:		if (request != PCNULL && request != PCDSTOP)			return (0);		break;	case PS_LOST:		if (request != PCNULL) {			errno = EAGAIN;			return (-1);		}		break;	case PS_UNDEAD:	case PS_DEAD:	case PS_IDLE:		if (request != PCNULL) {			errno = ENOENT;			return (-1);		}		break;	default:	/* corrupted state */		dprintf("Pstopstatus: corrupted state: %d\n", P->state);		errno = EINVAL;		return (-1);	}	ctl[0] = PCDSTOP;	ctl[1] = PCTWSTOP;	ctl[2] = (long)msec;	rc = 0;	switch (request) {	case PCSTOP:		rc = write(ctlfd, &ctl[0], 3*sizeof (long));		break;	case PCWSTOP:		rc = write(ctlfd, &ctl[1], 2*sizeof (long));		break;	case PCDSTOP:		rc = write(ctlfd, &ctl[0], 1*sizeof (long));		break;	case PCNULL:		if (P->state == PS_DEAD || P->state == PS_IDLE)			return (0);		break;	default:	/* programming error */		errno = EINVAL;		return (-1);	}	err = (rc < 0)? errno : 0;	Psync(P);	if (P->agentstatfd < 0) {		if (pread(P->statfd, &P->status,		    sizeof (P->status), (off_t)0) < 0)			err = errno;	} else {		if (pread(P->agentstatfd, &P->status.pr_lwp,		    sizeof (P->status.pr_lwp), (off_t)0) < 0)			err = errno;		P->status.pr_flags = P->status.pr_lwp.pr_flags;	}	if (err) {		switch (err) {		case EINTR:		/* user typed ctl-C */		case ERESTART:			dprintf("Pstopstatus: EINTR\n");			break;		case EAGAIN:		/* we lost control of the the process */		case EOVERFLOW:			dprintf("Pstopstatus: PS_LOST, errno=%d\n", err);			P->state = PS_LOST;			break;		default:		/* check for dead process */			if (_libproc_debug) {				const char *errstr;				switch (request) {				case PCNULL:					errstr = "Pstopstatus PCNULL"; break;				case PCSTOP:					errstr = "Pstopstatus PCSTOP"; break;				case PCDSTOP:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -