diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2016-12-06 04:22:38 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2016-12-06 04:22:38 +0000 |
| commit | b043b5dc6bf70af9d188fc37d201bb35dab8feec (patch) | |
| tree | b47ad9b1b0fd341f0774f71371efe6e60091519c /lib/libproc | |
| parent | c156354ff82167219f10fd80c55f6452acb60328 (diff) | |
Notes
Diffstat (limited to 'lib/libproc')
| -rw-r--r-- | lib/libproc/libproc.h | 5 | ||||
| -rw-r--r-- | lib/libproc/proc_create.c | 41 | ||||
| -rw-r--r-- | lib/libproc/proc_util.c | 12 |
3 files changed, 36 insertions, 22 deletions
diff --git a/lib/libproc/libproc.h b/lib/libproc/libproc.h index 25f8aa62f12b..53e92edeb191 100644 --- a/lib/libproc/libproc.h +++ b/lib/libproc/libproc.h @@ -50,6 +50,11 @@ typedef void (*proc_child_func)(void *); #define PS_DEAD 5 #define PS_LOST 6 +/* Flags for proc_attach(). */ +#define PATTACH_FORCE 0x01 +#define PATTACH_RDONLY 0x02 +#define PATTACH_NOSTOP 0x04 + /* Reason values for proc_detach(). */ #define PRELEASE_HANG 1 #define PRELEASE_KILL 2 diff --git a/lib/libproc/proc_create.c b/lib/libproc/proc_create.c index 36f27099c739..69de8cb119bd 100644 --- a/lib/libproc/proc_create.c +++ b/lib/libproc/proc_create.c @@ -127,7 +127,7 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl) struct proc_handle *phdl; int error, status; - if (pid == 0 || pid == getpid()) + if (pid == 0 || (pid == getpid() && (flags & PATTACH_RDONLY) == 0)) return (EINVAL); if (elf_version(EV_CURRENT) == EV_NONE) return (ENOENT); @@ -140,27 +140,32 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl) if (error != 0) goto out; - if (ptrace(PT_ATTACH, proc_getpid(phdl), 0, 0) != 0) { - error = errno; - DPRINTF("ERROR: cannot ptrace child process %d", pid); - goto out; - } + if ((flags & PATTACH_RDONLY) == 0) { + if (ptrace(PT_ATTACH, proc_getpid(phdl), 0, 0) != 0) { + error = errno; + DPRINTF("ERROR: cannot ptrace child process %d", pid); + goto out; + } - /* Wait for the child process to stop. */ - if (waitpid(pid, &status, WUNTRACED) == -1) { - error = errno; - DPRINTF("ERROR: child process %d didn't stop as expected", pid); - goto out; - } + /* Wait for the child process to stop. */ + if (waitpid(pid, &status, WUNTRACED) == -1) { + error = errno; + DPRINTF("ERROR: child process %d didn't stop as expected", pid); + goto out; + } - /* Check for an unexpected status. */ - if (!WIFSTOPPED(status)) - DPRINTFX("ERROR: child process %d status 0x%x", pid, status); - else - phdl->status = PS_STOP; + /* Check for an unexpected status. */ + if (!WIFSTOPPED(status)) + DPRINTFX("ERROR: child process %d status 0x%x", pid, status); + else + phdl->status = PS_STOP; + + if ((flags & PATTACH_NOSTOP) != 0) + proc_continue(phdl); + } out: - if (error && phdl != NULL) { + if (error != 0 && phdl != NULL) { proc_free(phdl); phdl = NULL; } diff --git a/lib/libproc/proc_util.c b/lib/libproc/proc_util.c index 3267813243ab..280c57e58941 100644 --- a/lib/libproc/proc_util.c +++ b/lib/libproc/proc_util.c @@ -87,21 +87,25 @@ proc_detach(struct proc_handle *phdl, int reason) if (phdl == NULL) return (EINVAL); + if (reason == PRELEASE_HANG) + return (EINVAL); if (reason == PRELEASE_KILL) { kill(proc_getpid(phdl), SIGKILL); - return (0); + goto free; } + if ((phdl->flags & PATTACH_RDONLY) != 0) + goto free; pid = proc_getpid(phdl); if (ptrace(PT_DETACH, pid, 0, 0) != 0 && errno == ESRCH) - return (0); + goto free; if (errno == EBUSY) { kill(pid, SIGSTOP); waitpid(pid, &status, WUNTRACED); ptrace(PT_DETACH, pid, 0, 0); kill(pid, SIGCONT); - return (0); } - +free: + proc_free(phdl); return (0); } |
