aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2016-12-06 04:22:38 +0000
committerMark Johnston <markj@FreeBSD.org>2016-12-06 04:22:38 +0000
commitb043b5dc6bf70af9d188fc37d201bb35dab8feec (patch)
treeb47ad9b1b0fd341f0774f71371efe6e60091519c
parentc156354ff82167219f10fd80c55f6452acb60328 (diff)
downloadsrc-b043b5dc6bf70af9d188fc37d201bb35dab8feec.tar.gz
src-b043b5dc6bf70af9d188fc37d201bb35dab8feec.zip
libproc: Add support for some proc_attach() flags.
This change adds some handling for the equivalent of Solaris' PGRAB_* flags. In particular, support for PGRAB_RDONLY is needed to avoid a nasty deadlock: dtrace(1) may otherwise stop the master process for its pseudo-terminal and end up blocking while writing to standard output.
Notes
Notes: svn path=/head/; revision=309597
-rw-r--r--cddl/compat/opensolaris/include/libproc.h3
-rw-r--r--cddl/lib/libdtrace/libproc_compat.h3
-rw-r--r--lib/libproc/libproc.h5
-rw-r--r--lib/libproc/proc_create.c41
-rw-r--r--lib/libproc/proc_util.c12
5 files changed, 39 insertions, 25 deletions
diff --git a/cddl/compat/opensolaris/include/libproc.h b/cddl/compat/opensolaris/include/libproc.h
index 565b0a43dd72..428fa6cf53fe 100644
--- a/cddl/compat/opensolaris/include/libproc.h
+++ b/cddl/compat/opensolaris/include/libproc.h
@@ -38,9 +38,6 @@
#define PR_RLC 0x0001
#define PR_KLC 0x0002
-#define PGRAB_RDONLY O_RDONLY
-#define PGRAB_FORCE 0
-
#include_next <libproc.h>
#endif
diff --git a/cddl/lib/libdtrace/libproc_compat.h b/cddl/lib/libdtrace/libproc_compat.h
index 0bb9e05424b7..167858cf675c 100644
--- a/cddl/lib/libdtrace/libproc_compat.h
+++ b/cddl/lib/libdtrace/libproc_compat.h
@@ -34,6 +34,9 @@
* Functions sorted alphabetically.
*/
#define PR_LMID_EVERY 0
+#define PGRAB_RDONLY PATTACH_RDONLY
+#define PGRAB_FORCE PATTACH_FORCE
+
#define Psetrun(p, a1, a2) proc_continue((p))
#define Pxlookup_by_addr(p, a, n, s, sym, i) \
proc_addr2sym(p, a, n, s, sym)
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);
}