mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
Revert "ctrools: Rewrite task/threads stopping engine"
This reverts commit 6da51eee3f
.
It breaks transition/file_read test case
This commit is contained in:
252
cr-dump.c
252
cr-dump.c
@@ -724,7 +724,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_threads(struct pstree_item *item, int pid_dir)
|
||||
static int parse_threads(pid_t pid, int pid_dir, struct pstree_item *item)
|
||||
{
|
||||
struct dirent *de;
|
||||
DIR *dir;
|
||||
@@ -733,7 +733,7 @@ static int parse_threads(struct pstree_item *item, int pid_dir)
|
||||
|
||||
dir = opendir_proc(pid_dir, "task");
|
||||
if (!dir) {
|
||||
pr_perror("Can't open %d/task", item->pid);
|
||||
pr_perror("Can't open %d/task", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -762,7 +762,7 @@ static int parse_threads(struct pstree_item *item, int pid_dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_children(struct pstree_item *item, int pid_dir)
|
||||
static int parse_children(pid_t pid, int pid_dir, struct pstree_item *item)
|
||||
{
|
||||
FILE *file;
|
||||
char *tok;
|
||||
@@ -774,7 +774,7 @@ static int parse_children(struct pstree_item *item, int pid_dir)
|
||||
file = fopen_proc(pid_dir, "task/%d/children", item->threads[i]);
|
||||
if (!file) {
|
||||
pr_perror("Can't open %d children %d",
|
||||
item->pid, item->threads[i]);
|
||||
pid, item->threads[i]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -806,154 +806,91 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void unseize_task_and_threads(struct pstree_item *item, enum cr_task_state st)
|
||||
static struct pstree_item *add_pstree_entry(pid_t pid, int pid_dir, struct list_head *list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < item->nr_threads; i++)
|
||||
unseize_task(item->threads[i], st); /* item->pid will be here */
|
||||
}
|
||||
|
||||
static void pstree_switch_state(struct list_head *list, struct cr_options *opts)
|
||||
{
|
||||
struct pstree_item *item;
|
||||
|
||||
list_for_each_entry(item, list, list) {
|
||||
unseize_task_and_threads(item, opts->final_state);
|
||||
if (opts->leader_only)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int seize_threads(struct pstree_item *item)
|
||||
{
|
||||
int i = 0, ret;
|
||||
|
||||
if ((item->state == TASK_DEAD) && (item->nr_threads > 1)) {
|
||||
pr_err("Zombies with threads are not supported\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < item->nr_threads; i++) {
|
||||
if (item->pid == item->threads[i])
|
||||
continue;
|
||||
|
||||
pr_info("\tSeizing %d's %d thread\n", item->pid, item->threads[i]);
|
||||
ret = seize_task(item->threads[i]);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (ret == TASK_SHOULD_BE_DEAD) {
|
||||
pr_err("Potentially zombie thread not supported\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ret == TASK_STOPPED) {
|
||||
pr_err("Stopped threads not supported\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i--; i >= 0; i--) {
|
||||
if (item->pid == item->threads[i])
|
||||
continue;
|
||||
|
||||
unseize_task(item->threads[i], CR_TASK_STOP /* FIXME */);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct pstree_item *collect_task(pid_t pid, struct list_head *list)
|
||||
{
|
||||
int ret, pid_dir;
|
||||
struct pstree_item *item;
|
||||
|
||||
item = xzalloc(sizeof(*item));
|
||||
if (!item)
|
||||
goto err;
|
||||
|
||||
ret = seize_task(pid);
|
||||
if (ret < 0)
|
||||
if (parse_threads(pid, pid_dir, item))
|
||||
goto err_free;
|
||||
|
||||
if (parse_children(pid, pid_dir, item))
|
||||
goto err_free;
|
||||
|
||||
pr_info("Seized task %d, state %d\n", pid, ret);
|
||||
item->pid = pid;
|
||||
item->state = ret;
|
||||
|
||||
pid_dir = open_pid_proc(pid);
|
||||
if (pid_dir < 0)
|
||||
goto err_free;
|
||||
|
||||
if (item->state == TASK_SHOULD_BE_DEAD) {
|
||||
struct proc_pid_stat_small ps;
|
||||
|
||||
ret = parse_pid_stat_small(pid, pid_dir, &ps);
|
||||
if (ret < 0)
|
||||
goto err_close;
|
||||
|
||||
if (ps.state != 'Z') {
|
||||
pr_err("Unseizeable non-zombie %d found, state %c\n",
|
||||
item->pid, ps.state);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
item->state = TASK_DEAD;
|
||||
}
|
||||
|
||||
ret = parse_threads(item, pid_dir);
|
||||
if (ret < 0)
|
||||
goto err_close;
|
||||
|
||||
ret = seize_threads(item);
|
||||
if (ret < 0)
|
||||
goto err_close;
|
||||
|
||||
ret = parse_children(item, pid_dir);
|
||||
if (ret < 0)
|
||||
goto err_close;
|
||||
|
||||
if ((item->state == TASK_DEAD) && (item->nr_children > 0)) {
|
||||
pr_err("Zombie with children?! O_o Run, run, run!\n");
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
close(pid_dir);
|
||||
list_add_tail(&item->list, list);
|
||||
pr_info("Collected %d in %d state\n", item->pid, item->state);
|
||||
return item;
|
||||
|
||||
err_close:
|
||||
close(pid_dir);
|
||||
err_free:
|
||||
xfree(item->children);
|
||||
xfree(item->threads);
|
||||
xfree(item->children);
|
||||
xfree(item);
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int collect_pstree(pid_t pid, struct list_head *pstree_list, int leader_only)
|
||||
static const int state_sigs[] = {
|
||||
[CR_TASK_STOP] = SIGSTOP,
|
||||
[CR_TASK_RUN] = SIGCONT,
|
||||
[CR_TASK_KILL] = SIGKILL,
|
||||
};
|
||||
|
||||
static int ps_switch_state(int pid, enum cr_task_state state)
|
||||
{
|
||||
return kill(pid, state_sigs[state]);
|
||||
}
|
||||
|
||||
static void pstree_switch_state(struct list_head *list,
|
||||
enum cr_task_state state, int leader_only)
|
||||
{
|
||||
struct pstree_item *item;
|
||||
int i;
|
||||
|
||||
pr_info("Collecting tasks starting from %d\n", pid);
|
||||
item = collect_task(pid, pstree_list);
|
||||
if (item == NULL)
|
||||
return -1;
|
||||
/*
|
||||
* Since ptrace-seize doesn't work on frozen tasks
|
||||
* we stick with explicit tasks stopping via stop
|
||||
* signal, but in future it's aimed to switch to
|
||||
* kernel freezer.
|
||||
*/
|
||||
|
||||
list_for_each_entry(item, list, list) {
|
||||
kill(item->pid, state_sigs[state]);
|
||||
if (leader_only)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < item->nr_children; i++)
|
||||
if (collect_pstree(item->children[i], pstree_list, 0) < 0)
|
||||
return -1;
|
||||
static int collect_pstree(pid_t pid, struct list_head *pstree_list)
|
||||
{
|
||||
struct pstree_item *item;
|
||||
unsigned long i;
|
||||
int pid_dir;
|
||||
int ret = -1;
|
||||
|
||||
return 0;
|
||||
pid_dir = open_pid_proc(pid);
|
||||
if (pid_dir < 0)
|
||||
goto err;
|
||||
|
||||
if (ps_switch_state(pid, CR_TASK_STOP))
|
||||
goto err;
|
||||
|
||||
item = add_pstree_entry(pid, pid_dir, pstree_list);
|
||||
if (!item)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < item->nr_children; i++) {
|
||||
ret = collect_pstree(item->children[i], pstree_list);
|
||||
if (ret)
|
||||
goto err_close;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
err_close:
|
||||
close(pid_dir);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset *cr_fdset)
|
||||
@@ -1148,12 +1085,25 @@ static int dump_task_thread(pid_t pid, struct cr_fdset *cr_fdset)
|
||||
if (!core)
|
||||
goto err;
|
||||
|
||||
ret = seize_task(pid);
|
||||
if (ret) {
|
||||
pr_err("Failed to seize thread (pid: %d) with %d\n",
|
||||
pid, ret);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
pr_info("Dumping GP/FPU registers ... ");
|
||||
ret = get_task_regs(pid, core);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
pr_info("OK\n");
|
||||
|
||||
ret = unseize_task(pid);
|
||||
if (ret) {
|
||||
pr_err("Can't unsieze thread (pid: %d)\n", pid);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
core->tc.task_state = TASK_ALIVE;
|
||||
core->tc.exit_code = 0;
|
||||
|
||||
@@ -1172,6 +1122,16 @@ static int dump_one_zombie(struct pstree_item *item, struct proc_pid_stat *pps,
|
||||
{
|
||||
struct core_entry *core;
|
||||
|
||||
if (item->nr_children) {
|
||||
pr_err("Zombie %d with children.\n", item->pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (item->nr_threads > 1) {
|
||||
pr_err("Zombie %d with threads.\n", item->pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cr_fdset = cr_fdset_open(item->pid, CR_FD_DESC_CORE, cr_fdset);
|
||||
if (cr_fdset == NULL)
|
||||
return -1;
|
||||
@@ -1231,11 +1191,6 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
|
||||
pr_info("Dumping task (pid: %d)\n", pid);
|
||||
pr_info("========================================\n");
|
||||
|
||||
if (item->state == TASK_STOPPED) {
|
||||
pr_err("Stopped tasks are not supported\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
pid_dir = open_pid_proc(pid);
|
||||
if (pid_dir < 0) {
|
||||
pr_perror("Can't open %d proc dir", pid);
|
||||
@@ -1247,8 +1202,17 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (item->state == TASK_DEAD)
|
||||
switch (pps_buf.state) {
|
||||
case 'Z':
|
||||
return dump_one_zombie(item, &pps_buf, cr_fdset);
|
||||
case 'T':
|
||||
/* Stopped -- can dump one */
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
pr_err("Task in bad state: %c\n", pps_buf.state);
|
||||
goto err;
|
||||
};
|
||||
|
||||
ret = -1;
|
||||
if (!cr_fdset_open(item->pid, CR_FD_DESC_TASK, cr_fdset))
|
||||
@@ -1260,6 +1224,13 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = seize_task(pid);
|
||||
if (ret) {
|
||||
pr_err("Failed to seize task (pid: %d) with %d\n",
|
||||
pid, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = dump_task_core_seized(pid, pid_dir, &pps_buf, cr_fdset);
|
||||
if (ret) {
|
||||
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
|
||||
@@ -1302,6 +1273,12 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = unseize_task(pid);
|
||||
if (ret) {
|
||||
pr_err("Can't unsieze (pid: %d) task\n", pid);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = dump_task_files(pid, pid_dir, cr_fdset);
|
||||
if (ret) {
|
||||
pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
|
||||
@@ -1349,7 +1326,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
|
||||
pr_info("Dumping process (pid: %d)\n", pid);
|
||||
pr_info("========================================\n");
|
||||
|
||||
if (collect_pstree(pid, &pstree_list, opts->leader_only))
|
||||
if (collect_pstree(pid, &pstree_list))
|
||||
goto err;
|
||||
|
||||
if (opts->namespaces_flags) {
|
||||
@@ -1390,8 +1367,17 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
pstree_switch_state(&pstree_list, opts);
|
||||
switch (opts->final_state) {
|
||||
case CR_TASK_RUN:
|
||||
case CR_TASK_KILL:
|
||||
pstree_switch_state(&pstree_list,
|
||||
opts->final_state, opts->leader_only);
|
||||
case CR_TASK_STOP: /* they are already stopped */
|
||||
break;
|
||||
}
|
||||
|
||||
free_pstree(&pstree_list);
|
||||
|
||||
close_cr_fdset(&cr_fdset);
|
||||
|
||||
return ret;
|
||||
|
11
crtools.c
11
crtools.c
@@ -289,7 +289,7 @@ int main(int argc, char *argv[])
|
||||
int action = -1;
|
||||
int log_inited = 0;
|
||||
|
||||
static const char short_opts[] = "dsf:p:t:hcD:o:n:";
|
||||
static const char short_opts[] = "df:p:t:hcD:o:n:";
|
||||
|
||||
BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE);
|
||||
|
||||
@@ -306,9 +306,6 @@ int main(int argc, char *argv[])
|
||||
for (opt = getopt_long(argc - 1, argv + 1, short_opts, NULL, &idx); opt != -1;
|
||||
opt = getopt_long(argc - 1, argv + 1, short_opts, NULL, &idx)) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
opts.final_state = CR_TASK_STOP;
|
||||
break;
|
||||
case 'p':
|
||||
pid = atoi(optarg);
|
||||
opts.leader_only = true;
|
||||
@@ -319,6 +316,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'c':
|
||||
opts.show_pages_content = true;
|
||||
opts.final_state = CR_TASK_RUN;
|
||||
break;
|
||||
case 'f':
|
||||
opts.show_dump_file = optarg;
|
||||
@@ -400,9 +398,10 @@ usage:
|
||||
printk(" -p checkpoint/restore only a single process identified by pid\n");
|
||||
printk(" -t checkpoint/restore the whole process tree identified by pid\n");
|
||||
printk(" -f show contents of a checkpoint file\n");
|
||||
printk(" -c show contents of pages dumped in hexdump format\n");
|
||||
printk(" -c in case of checkpoint -- continue running the process after\n"
|
||||
" checkpoint complete, in case of showing file contents --\n"
|
||||
" show contents of pages dumped in hexdump format\n");
|
||||
printk(" -d detach after restore\n");
|
||||
printk(" -s leave tasks in stopped state after checkpoint instead of killing them\n");
|
||||
printk(" -n checkpoint/restore namespaces - values must be separated by comma\n");
|
||||
printk(" supported: uts, ipc\n");
|
||||
|
||||
|
@@ -43,6 +43,7 @@ enum {
|
||||
};
|
||||
|
||||
enum cr_task_state {
|
||||
CR_TASK_RUN,
|
||||
CR_TASK_STOP,
|
||||
CR_TASK_KILL,
|
||||
};
|
||||
@@ -138,7 +139,6 @@ struct vma_area {
|
||||
struct pstree_item {
|
||||
struct list_head list;
|
||||
pid_t pid; /* leader pid */
|
||||
int state; /* TASK_XXX constants */
|
||||
u32 nr_children; /* number of children */
|
||||
u32 nr_threads; /* number of threads */
|
||||
u32 *threads; /* array of threads */
|
||||
|
@@ -317,7 +317,6 @@ struct core_entry {
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define TASK_SHOULD_BE_DEAD 0x0
|
||||
#define TASK_ALIVE 0x1
|
||||
#define TASK_DEAD 0x2
|
||||
#define TASK_STOPPED 0x3 /* FIXME - implement */
|
||||
|
@@ -4,12 +4,6 @@
|
||||
#define PROC_TASK_COMM_LEN 32
|
||||
#define PROC_TASK_COMM_LEN_FMT "(%31s"
|
||||
|
||||
struct proc_pid_stat_small {
|
||||
int pid;
|
||||
char comm[PROC_TASK_COMM_LEN];
|
||||
char state;
|
||||
};
|
||||
|
||||
struct proc_pid_stat {
|
||||
int pid;
|
||||
char comm[PROC_TASK_COMM_LEN];
|
||||
@@ -78,7 +72,6 @@ struct proc_status_creds {
|
||||
};
|
||||
|
||||
extern int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s);
|
||||
extern int parse_pid_stat_small(pid_t pid, int pid_dir, struct proc_pid_stat_small *s);
|
||||
extern int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files);
|
||||
extern int parse_pid_status(int pid_dir, struct proc_status_creds *);
|
||||
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#define PTRACE_O_TRACEEXIT 0x00000040
|
||||
|
||||
extern int seize_task(pid_t pid);
|
||||
extern int unseize_task(pid_t pid, enum cr_task_state st);
|
||||
extern int unseize_task(pid_t pid);
|
||||
extern int ptrace_peek_area(pid_t pid, void *dst, void *addr, long bytes);
|
||||
extern int ptrace_poke_area(pid_t pid, void *src, void *addr, long bytes);
|
||||
extern int ptrace_show_area(pid_t pid, void *addr, long bytes);
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "crtools.h"
|
||||
#include "compiler.h"
|
||||
#include "syscall.h"
|
||||
#include "types.h"
|
||||
|
30
proc_parse.c
30
proc_parse.c
@@ -175,36 +175,6 @@ err_bogus_mapping:
|
||||
goto err;
|
||||
}
|
||||
|
||||
int parse_pid_stat_small(pid_t pid, int pid_dir, struct proc_pid_stat_small *s)
|
||||
{
|
||||
FILE *f;
|
||||
char *tok;
|
||||
int n;
|
||||
|
||||
f = fopen_proc(pid_dir, "stat");
|
||||
if (f == NULL) {
|
||||
pr_perror("Can't open %d's stat", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
n = fscanf(f, "%d " PROC_TASK_COMM_LEN_FMT " %c",
|
||||
&s->pid, s->comm, &s->state);
|
||||
|
||||
if (n < 3) {
|
||||
pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->comm[PROC_TASK_COMM_LEN-1] = '\0';
|
||||
tok = strchr(s->comm, ')');
|
||||
if (tok)
|
||||
*tok = '\0';
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_pid_stat(pid_t pid, int pid_dir, struct proc_pid_stat *s)
|
||||
{
|
||||
FILE *f;
|
||||
|
65
ptrace.c
65
ptrace.c
@@ -13,22 +13,14 @@
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "crtools.h"
|
||||
#include "compiler.h"
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
#include "ptrace.h"
|
||||
|
||||
int unseize_task(pid_t pid, enum cr_task_state st)
|
||||
int unseize_task(pid_t pid)
|
||||
{
|
||||
if (st == CR_TASK_STOP)
|
||||
return ptrace(PTRACE_DETACH, pid, NULL, NULL);
|
||||
else if (st == CR_TASK_KILL)
|
||||
return ptrace(PTRACE_KILL, pid, NULL, NULL);
|
||||
else {
|
||||
BUG_ON(1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -38,61 +30,48 @@ int unseize_task(pid_t pid, enum cr_task_state st)
|
||||
* of it so the task would not know if it was saddled
|
||||
* up with someone else.
|
||||
*/
|
||||
|
||||
int seize_task(pid_t pid)
|
||||
{
|
||||
siginfo_t si;
|
||||
int status;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
ret = ptrace(PTRACE_SEIZE, pid, NULL,
|
||||
(void *)(unsigned long)PTRACE_SEIZE_DEVEL);
|
||||
if (ret < 0)
|
||||
return TASK_SHOULD_BE_DEAD; /* Caller should verify it's really dead */
|
||||
if (ret < 0) {
|
||||
pr_perror("Can't seize task");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ptrace(PTRACE_INTERRUPT, pid, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
pr_perror("SEIZE %d: can't interrupt task", pid);
|
||||
pr_perror("Can't interrupt task");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = wait4(pid, &status, __WALL, NULL);
|
||||
if (ret < 0) {
|
||||
pr_perror("SEIZE %d: can't wait task", pid);
|
||||
ret = -10;
|
||||
if (wait4(pid, &status, __WALL, NULL) != pid)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ret != pid) {
|
||||
pr_err("SEIZE %d: wrong task attached (%d)\n", pid, ret);
|
||||
ret = -20;
|
||||
if (!WIFSTOPPED(status))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!WIFSTOPPED(status)) {
|
||||
pr_err("SEIZE %d: task not stopped after seize\n", pid);
|
||||
goto err;
|
||||
}
|
||||
jerr_rc(ptrace(PTRACE_GETSIGINFO, pid, NULL, &si), ret, err_cont);
|
||||
|
||||
ret = ptrace(PTRACE_GETSIGINFO, pid, NULL, &si);
|
||||
if (ret < 0) {
|
||||
pr_perror("SEIZE %d: can't read signfo", pid);
|
||||
goto err;
|
||||
}
|
||||
ret = -30;
|
||||
if ((si.si_code >> 8) != PTRACE_EVENT_STOP)
|
||||
goto err_cont;
|
||||
|
||||
if ((si.si_code >> 8) != PTRACE_EVENT_STOP) {
|
||||
pr_err("SEIZE %d: wrong stop event received 0x%x\n", pid,
|
||||
(unsigned int)si.si_code);
|
||||
goto err;
|
||||
}
|
||||
jerr_rc(ptrace(PTRACE_SETOPTIONS, pid, NULL,
|
||||
(void *)(unsigned long)PTRACE_O_TRACEEXIT), ret, err_cont);
|
||||
|
||||
if (si.si_signo == SIGTRAP)
|
||||
return TASK_ALIVE;
|
||||
else if (si.si_signo == SIGSTOP)
|
||||
return TASK_STOPPED;
|
||||
|
||||
pr_err("SEIZE %d: unsupported stop signal %d\n", pid, si.si_signo);
|
||||
err:
|
||||
unseize_task(pid, CR_TASK_STOP);
|
||||
return -1;
|
||||
return ret;
|
||||
|
||||
err_cont:
|
||||
kill(pid, SIGCONT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
int ptrace_show_area_r(pid_t pid, void *addr, long bytes)
|
||||
|
Reference in New Issue
Block a user