[CRIU] [PATCH 1/3] dump: save /proc/pid/cmdline

Ruslan Kuprieiev kupruser at gmail.com
Sun Apr 19 12:04:35 PDT 2015


Sigh... Forgot about a cover letter...

So I've tested it with gdb and was able to successfully backtrace, 
switch frames,
read registers, read xsave-related stuff and so on.
The overall structure is something in between kernel-generated and 
gdb-generated
core dumps.
Some signal-related stuff is not filled(still need to figure out what 
would be a proper
content in our case, when there is no signals involved in generating 
core dump) as
well as vvar and vsyscall are for now just filled with zeroes.
The only architecture supported for now is x86_64.

I'm still in the process of solving all the caveats listed above, but I 
think we could
already apply these patches as it already works.

Feedback is appreciated =).


On 19.04.15 21:50, Ruslan Kuprieiev wrote:
> We need it to produce core dump notes and don't use it on restore.
>
> Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
> ---
>   cr-dump.c            | 13 +++++++++++--
>   include/image.h      |  1 +
>   include/proc_parse.h |  1 +
>   proc_parse.c         | 35 +++++++++++++++++++++++++++++++++++
>   protobuf/core.proto  |  2 ++
>   pstree.c             |  4 +++-
>   6 files changed, 53 insertions(+), 3 deletions(-)
>
> diff --git a/cr-dump.c b/cr-dump.c
> index ac41865..0ec3444 100644
> --- a/cr-dump.c
> +++ b/cr-dump.c
> @@ -653,7 +653,8 @@ int dump_thread_core(int pid, CoreEntry *core, const struct parasite_dump_thread
>   static int dump_task_core_all(struct pstree_item *item,
>   		const struct proc_pid_stat *stat,
>   		const struct parasite_dump_misc *misc,
> -		const struct cr_imgset *cr_imgset)
> +		const struct cr_imgset *cr_imgset,
> +		char cmdline[])
>   {
>   	struct cr_img *img;
>   	CoreEntry *core = item->core[0];
> @@ -669,6 +670,7 @@ static int dump_task_core_all(struct pstree_item *item,
>   		goto err;
>   
>   	strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
> +	strncpy((char *)core->tc->cmdline, cmdline, TASK_CMDLINE_LEN);
>   	core->tc->flags = stat->flags;
>   	core->tc->task_state = item->state;
>   	core->tc->exit_code = 0;
> @@ -1459,6 +1461,7 @@ static int dump_one_task(struct pstree_item *item)
>   	struct cr_imgset *cr_imgset = NULL;
>   	struct parasite_drain_fd *dfds = NULL;
>   	struct proc_posix_timers_stat proc_args;
> +	char cmdline[TASK_CMDLINE_LEN];
>   
>   	INIT_LIST_HEAD(&vmas.h);
>   	vmas.nr = 0;
> @@ -1478,6 +1481,12 @@ static int dump_one_task(struct pstree_item *item)
>   	if (ret < 0)
>   		goto err;
>   
> +	ret = parse_pid_cmdline(pid, cmdline);
> +	if (ret) {
> +		pr_err("Parse cmdline (pid: %d) failed with %d\n", pid, ret);
> +		goto err;
> +	}
> +
>   	ret = collect_mappings(pid, &vmas);
>   	if (ret) {
>   		pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
> @@ -1604,7 +1613,7 @@ static int dump_one_task(struct pstree_item *item)
>   		goto err_cure;
>   	}
>   
> -	ret = dump_task_core_all(item, &pps_buf, &misc, cr_imgset);
> +	ret = dump_task_core_all(item, &pps_buf, &misc, cr_imgset, cmdline);
>   	if (ret) {
>   		pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
>   		goto err_cure;
> diff --git a/include/image.h b/include/image.h
> index 55e63dd..3e6d584 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -106,6 +106,7 @@
>   #define CR_CAP_SIZE	2
>   
>   #define TASK_COMM_LEN 16
> +#define TASK_CMDLINE_LEN 80
>   
>   #define TASK_ALIVE		0x1
>   #define TASK_DEAD		0x2
> diff --git a/include/proc_parse.h b/include/proc_parse.h
> index e5d59d2..3ca93ef 100644
> --- a/include/proc_parse.h
> +++ b/include/proc_parse.h
> @@ -157,6 +157,7 @@ struct vm_area_list;
>   extern bool add_skip_mount(const char *mountpoint);
>   extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump);
>   extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
> +extern int parse_pid_cmdline(pid_t pid, char cmdline[]);
>   extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list);
>   extern int parse_self_maps_lite(struct vm_area_list *vms);
>   extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
> diff --git a/proc_parse.c b/proc_parse.c
> index 5d50979..a283c9a 100644
> --- a/proc_parse.c
> +++ b/proc_parse.c
> @@ -615,6 +615,41 @@ err_n:
>   
>   }
>   
> +int parse_pid_cmdline(pid_t pid, char cmdline[])
> +{
> +	int fd;
> +	ssize_t n;
> +	char *p;
> +
> +	fd = open_proc(pid, "cmdline");
> +	if (fd < 0)
> +		return -1;
> +
> +	n = read(fd, buf, BUF_SIZE);
> +	/* 0 is okay, as it may be zombie */
> +	if (n < 0) {
> +		pr_perror("Can't read cmdline for %d\n", pid);
> +		close(fd);
> +		return -1;
> +	}
> +
> +	close(fd);
> +
> +	/*
> +	 * cmdline contains null-separated strings,
> +	 * so we need to replace '\0's with spaces.
> +	 */
> +	for (p = buf; p < buf + n; p++)
> +		if (*p == '\0')
> +			*p = ' ';
> +
> +	*p = '\0';
> +
> +	strncpy(cmdline, buf, TASK_CMDLINE_LEN);
> +
> +	return 0;
> +}
> +
>   int parse_pid_stat(pid_t pid, struct proc_pid_stat *s)
>   {
>   	char *tok, *p;
> diff --git a/protobuf/core.proto b/protobuf/core.proto
> index 1f44a47..d6cce24 100644
> --- a/protobuf/core.proto
> +++ b/protobuf/core.proto
> @@ -25,6 +25,8 @@ message task_core_entry {
>   	optional uint32			cg_set		= 9;
>   
>   	optional signal_queue_entry	signals_s	= 10;
> +
> +	optional string			cmdline		= 11;
>   }
>   
>   message task_kobj_ids_entry {
> diff --git a/pstree.c b/pstree.c
> index 2dbcb04..f97423c 100644
> --- a/pstree.c
> +++ b/pstree.c
> @@ -37,7 +37,7 @@ CoreEntry *core_entry_alloc(int th, int tsk)
>   
>   	sz = sizeof(CoreEntry);
>   	if (tsk) {
> -		sz += sizeof(TaskCoreEntry) + TASK_COMM_LEN;
> +		sz += sizeof(TaskCoreEntry) + TASK_COMM_LEN + TASK_CMDLINE_LEN;
>   		if (th) {
>   			sz += sizeof(TaskRlimitsEntry);
>   			sz += RLIM_NLIMITS * sizeof(RlimitEntry *);
> @@ -60,6 +60,8 @@ CoreEntry *core_entry_alloc(int th, int tsk)
>   			task_core_entry__init(core->tc);
>   			core->tc->comm = xptr_pull_s(&m, TASK_COMM_LEN);
>   			memzero(core->tc->comm, TASK_COMM_LEN);
> +			core->tc->cmdline = xptr_pull_s(&m, TASK_CMDLINE_LEN);
> +			memzero(core->tc->cmdline, TASK_CMDLINE_LEN);
>   
>   			if (th) {
>   				TaskRlimitsEntry *rls;



More information about the CRIU mailing list