From c30f014a893cf0c84ce0092da09ff108fbb577e7 Mon Sep 17 00:00:00 2001 From: Adriana Szekeres Date: Tue, 22 Nov 2011 16:41:47 +0100 Subject: [PATCH] gcore command to coredump a process --- commands/Makefile | 2 +- commands/gcore/Makefile | 4 +++ commands/gcore/gcore.c | 66 ++++++++++++++++++++++++++++++++++++++ common/include/minix/com.h | 1 + include/sys/ptrace.h | 1 + nbsd_include/sys/ptrace.h | 1 + servers/pm/forkexit.c | 1 + servers/pm/main.c | 10 +++++- servers/pm/trace.c | 22 +++++++++++++ servers/vfs/main.c | 1 + servers/vfs/misc.c | 9 ++++-- 11 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 commands/gcore/Makefile create mode 100644 commands/gcore/gcore.c diff --git a/commands/Makefile b/commands/Makefile index 7ef211f58..99c1586f7 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -12,7 +12,7 @@ SUBDIR= aal add_route arp ash at autil awk \ dhrystone diff dirname dis386 dis88 diskctl du dumpcore \ ed eject elle elvis env expand factor file \ find finger fingerd fix fold format fortune fsck.mfs \ - ftp101 gcov-pull getty grep head hexdump host \ + ftp101 gcore gcov-pull getty grep head hexdump host \ hostaddr id ifconfig ifdef install \ intr ipcrm ipcs irdpd isoread join kill last leave \ less lex loadkeys loadramdisk logger login look lp \ diff --git a/commands/gcore/Makefile b/commands/gcore/Makefile new file mode 100644 index 000000000..4ad31cc0e --- /dev/null +++ b/commands/gcore/Makefile @@ -0,0 +1,4 @@ +PROG= gcore +MAN= + +.include diff --git a/commands/gcore/gcore.c b/commands/gcore/gcore.c new file mode 100644 index 000000000..8fa98e652 --- /dev/null +++ b/commands/gcore/gcore.c @@ -0,0 +1,66 @@ +/* gcore - create core file of running process */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + pid_t pid; + int r, status; + + if(argc != 2) { + printf("usage: %s \n", argv[0]); + return 1; + } + + pid = atoi(argv[1]); + + if (ptrace(T_ATTACH, pid, 0, 0) != 0) { + perror("ptrace(T_ATTACH)"); + return 1; + } + + if (waitpid(pid, &status, 0) != pid) { + perror("waitpid"); + return 1; + } + + while (WIFSTOPPED(status) && WSTOPSIG(status) != SIGSTOP) { + /* whatever happens here is fine */ + ptrace(T_RESUME, pid, 0, WSTOPSIG(status)); + + if (waitpid(pid, &status, 0) != pid) { + perror("waitpid"); + return 1; + } + } + + if (!WIFSTOPPED(status)) { + fprintf(stderr, "process died while attaching\n"); + return 1; + } + + if (ptrace(T_DUMPCORE, pid, 0, 0)) { + fprintf(stderr, "warning, dumpcore failed (%s)\n", + strerror(errno)); + } + + if (ptrace(T_DETACH, pid, 0, 0)) { + fprintf(stderr, "warning, detaching failed (%s)\n", + strerror(errno)); + } + + return r; +} diff --git a/common/include/minix/com.h b/common/include/minix/com.h index b82433f42..01a9094da 100644 --- a/common/include/minix/com.h +++ b/common/include/minix/com.h @@ -794,6 +794,7 @@ /* Additional parameters for PM_DUMPCORE */ # define PM_TERM_SIG m1_i2 /* process's termination signal */ +# define PM_TRACED_PROC m1_i3 /* required for T_DUMPCORE */ /* Parameters for the EXEC_NEWMEM call */ #define EXC_NM_PROC m1_i1 /* process that needs new map */ diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h index ddd17dc82..734b5ecd7 100644 --- a/include/sys/ptrace.h +++ b/include/sys/ptrace.h @@ -23,6 +23,7 @@ #define T_SETOPT 13 /* set trace options */ #define T_GETRANGE 14 /* get range of values */ #define T_SETRANGE 15 /* set range of values */ +#define T_DUMPCORE 16 /* dumps the core for the process with the given pid */ #define T_READB_INS 100 /* Read a byte from the text segment of an * untraced process (only for root) diff --git a/nbsd_include/sys/ptrace.h b/nbsd_include/sys/ptrace.h index b829771a4..59c1a442a 100644 --- a/nbsd_include/sys/ptrace.h +++ b/nbsd_include/sys/ptrace.h @@ -23,6 +23,7 @@ #define T_SETOPT 13 /* set trace options */ #define T_GETRANGE 14 /* get range of values */ #define T_SETRANGE 15 /* set range of values */ +#define T_DUMPCORE 16 /* dumps the core for the process with the given pid */ #define T_READB_INS 100 /* Read a byte from the text segment of an * untraced process (only for root) diff --git a/servers/pm/forkexit.c b/servers/pm/forkexit.c index c3d0c7bb2..9b1124ad9 100644 --- a/servers/pm/forkexit.c +++ b/servers/pm/forkexit.c @@ -317,6 +317,7 @@ int dump_core; /* flag indicating whether to dump core */ /* Tell VFS about the exiting process. */ m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT; m.PM_PROC = rmp->mp_endpoint; + m.PM_TRACED_PROC = rmp->mp_endpoint; if (dump_core) { m.PM_TERM_SIG = rmp->mp_sigstatus; diff --git a/servers/pm/main.c b/servers/pm/main.c index 90da3812f..12b41daf0 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -477,7 +477,15 @@ PRIVATE void handle_vfs_reply() if (m_in.PM_STATUS == OK) rmp->mp_sigstatus |= DUMPED; - exit_restart(rmp, TRUE /*dump_core*/); + if (m_in.PM_PROC == m_in.PM_TRACED_PROC) + /* The reply is to a core dump request + * for a killed process */ + exit_restart(rmp, TRUE /*dump_core*/); + else + /* The reply is to a core dump request + * for a traced process (T_DUMPCORE) */ + /* Wake up the original caller */ + setreply(rmp-mproc, rmp->mp_procgrp); break; diff --git a/servers/pm/trace.c b/servers/pm/trace.c index b6893a610..0786791de 100644 --- a/servers/pm/trace.c +++ b/servers/pm/trace.c @@ -42,6 +42,7 @@ PUBLIC int do_trace() register struct mproc *child; struct ptrace_range pr; int i, r, seg, req; + message m; req = m_in.request; @@ -90,6 +91,27 @@ PUBLIC int do_trace() mp->mp_reply.reply_trace = 0; return(OK); + case T_DUMPCORE: + if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); + + /* Allow dumpcore only if traced! */ + if (child->mp_tracer != who_p) return(EPERM); + + /* Tell VFS to dump the core. */ + m.m_type = PM_DUMPCORE; + m.PM_PROC = mp->mp_endpoint; + m.PM_TRACED_PROC = child->mp_endpoint; + /* Note that m.PM_PROC != m.PM_TRACED_PROC + * (we use this to differentiate between a VFS core dump reply for a + * an exiting process and the one for a traced process) */ + + m.PM_TERM_SIG = child->mp_sigstatus; + m.PM_PATH = child->mp_name; + + tell_vfs(mp, &m); + + return(SUSPEND); /* Suspend the process until we receive reply from VFS */ + case T_STOP: /* stop the process */ /* This call is not exposed to user programs, because its effect can be * achieved better by sending the traced process a signal with kill(2). diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 06b7536f5..05c3b035e 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -558,6 +558,7 @@ PRIVATE void service_pm() /* Reply status to PM */ m_out.m_type = PM_CORE_REPLY; m_out.PM_PROC = m_in.PM_PROC; + m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC; m_out.PM_STATUS = r; break; diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index b41fc0d28..1b406e9fa 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -581,8 +581,9 @@ int csig; char *exe_name; { int proc_s, r, old_who_e; - - okendpt(proc_e, &proc_s); + int traced_proc_e = m_in.PM_TRACED_PROC; + + okendpt(traced_proc_e, &proc_s); fp = &fproc[proc_s]; /* Open the core file */ @@ -603,10 +604,12 @@ char *exe_name; close_fd(fp, r); /* Terminate the process */ - free_proc(&fproc[proc_s], FP_EXITING); + if (traced_proc_e == proc_e) + free_proc(&fproc[proc_s], FP_EXITING); /* Restore the important variables that have been overwritten */ m_in.PM_PROC = proc_e; + m_in.PM_TRACED_PROC = traced_proc_e; who_e = old_who_e; return OK; -- 2.44.0