All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hitoshi Mitake <mitake.hitoshi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Ryusuke Konishi
	<konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Hitoshi Mitake
	<mitake.hitoshi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Hitoshi Mitake
	<mitake.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
Subject: Re: [PATCH] lib/cleaner_exec.c: get process ID of cleanerd through pipe
Date: Sun, 26 Jan 2014 01:46:09 +0900	[thread overview]
Message-ID: <87ha8sko1a.wl%mitake.hitoshi@gmail.com> (raw)
In-Reply-To: <1390397720-2259-1-git-send-email-konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>

At Wed, 22 Jan 2014 22:35:20 +0900,
Ryusuke Konishi wrote:
> 
> After applying commit 8ce4b524a1654ece478f54fce772cc0c16e3c559
> "cleanerd: call _exit(2) twice for ensuring not being a session
> leader", the mount helper program of nilfs2 no longer gets proper
> process ID (pid) of cleaner daemon, and umount.nilfs2 fails to kill
> cleanerd.
> 
> This fixes the issue by letting cleanerd print out the pid of spawned
> daemon and letting nilfs_launch_cleanerd() function read it through
> pipe.
> 
> Signed-off-by: Ryusuke Konishi <konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
> Cc: Hitoshi Mitake <mitake.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>

Looks good to me and sorry for my bug!
Reviewed-by: Hitoshi Mitake <mitake.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>

Thanks,
Hitoshi

> ---
>  lib/cleaner_exec.c       |   84 ++++++++++++++++++++++++++++++++++++++++++----
>  man/nilfs_cleanerd.8     |    3 ++
>  sbin/cleanerd/cleanerd.c |    3 ++
>  3 files changed, 83 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/cleaner_exec.c b/lib/cleaner_exec.c
> index edc55e3..5336c32 100644
> --- a/lib/cleaner_exec.c
> +++ b/lib/cleaner_exec.c
> @@ -114,6 +114,43 @@ static inline int process_is_alive(pid_t pid)
>  	return (kill(pid, 0) == 0);
>  }
>  
> +static int receive_pid(int fd, pid_t *ppid)
> +{
> +	char buf[100];
> +	unsigned long pid;
> +	FILE *fp;
> +	int ret;
> +
> +	fp = fdopen(fd, "r");
> +	if (!fp) {
> +		nilfs_cleaner_logger(
> +			LOG_ERR, _("Error: fdopen failed: %m"));
> +		close(fd);
> +		goto fail;
> +	}
> +
> +	/* read process ID of cleanerd through the given fd */
> +	while (fgets(buf, sizeof(buf), fp) != NULL) {
> +		/*
> +		 * fgets() is blocked during no child processes
> +		 * respond, but it will escape returning a NULL value
> +		 * and terminate the loop when all child processes
> +		 * close the given pipe (fd) including call of exit().
> +		 */
> +		ret = sscanf(buf, "NILFS_CLEANERD_PID=%lu", &pid);
> +		if (ret == 1) {
> +			*ppid = pid;
> +			fclose(fp); /* this also closes fd */
> +			return 0;
> +		}
> +	}
> +	fclose(fp);
> +fail:
> +	nilfs_cleaner_logger(
> +		LOG_WARNING, _("Warning: cannot get pid of cleanerd"));
> +	return -1;
> +}
> +
>  int nilfs_launch_cleanerd(const char *device, const char *mntdir,
>  			  unsigned long protperiod, pid_t *ppid)
>  {
> @@ -123,6 +160,7 @@ int nilfs_launch_cleanerd(const char *device, const char *mntdir,
>  	int i = 0;
>  	int ret;
>  	char buf[256];
> +	int pipes[2];
>  
>  	if (stat(cleanerd, &statbuf) != 0) {
>  		nilfs_cleaner_logger(LOG_ERR,  _("Error: %s not found"),
> @@ -130,8 +168,16 @@ int nilfs_launch_cleanerd(const char *device, const char *mntdir,
>  		return -1;
>  	}
>  
> +	ret = pipe(pipes);
> +	if (ret < 0) {
> +		nilfs_cleaner_logger(
> +			LOG_ERR, _("Error: failed to create pipe: %m"));
> +		return -1;
> +	}
> +
>  	ret = fork();
>  	if (ret == 0) {
> +		/* child */
>  		if (setgid(getgid()) < 0) {
>  			nilfs_cleaner_logger(
>  				LOG_ERR,
> @@ -159,16 +205,40 @@ int nilfs_launch_cleanerd(const char *device, const char *mntdir,
>  		sigdelset(&sigs, SIGSEGV);
>  		sigprocmask(SIG_UNBLOCK, &sigs, NULL);
>  
> +		close(pipes[0]);
> +		ret = dup2(pipes[1], STDOUT_FILENO);
> +		if (ret < 0) {
> +			nilfs_cleaner_logger(
> +				LOG_ERR,
> +				_("Error: failed to duplicate pipe: %m"));
> +			exit(1);
> +		}
> +		close(pipes[1]);
> +		
>  		execv(cleanerd, (char **)dargs);
>  		exit(1);   /* reach only if failed */
> -	} else if (ret != -1) {
> -		*ppid = ret;
> -		return 0; /* cleanerd started */
> +	} else if (ret > 0) {
> +		/* parent */
> +		close(pipes[1]);
> +
> +		/*
> +		 * fork() returns a pid of the child process, but we
> +		 * cannot use it because cleanerd internally fork()s
> +		 * and changes pid.
> +		 */
> +		ret = receive_pid(pipes[0], ppid);
> +		if (ret < 0)
> +			*ppid = 0;
> +		/*
> +		 * always return a success code because cleanerd has
> +		 * already started.
> +		 */
> +		return 0;
>  	} else {
> -		int errsv = errno;
> -		nilfs_cleaner_logger(LOG_ERR,
> -				     _("Error: could not fork: %s"),
> -				     strerror(errsv));
> +		nilfs_cleaner_logger(
> +			LOG_ERR, _("Error: could not fork: %m"));
> +		close(pipes[0]);
> +		close(pipes[1]);
>  	}
>  	return -1;
>  }
> diff --git a/man/nilfs_cleanerd.8 b/man/nilfs_cleanerd.8
> index 46caef2..fd1c48a 100644
> --- a/man/nilfs_cleanerd.8
> +++ b/man/nilfs_cleanerd.8
> @@ -24,6 +24,9 @@ users are recommended to invoke \fBnilfs_cleanerd\fP through
>  \fBmount.nilfs2\fP(8) or \fBmount\fP(8) and shutdown it through
>  \fBumount.nilfs2\fP(8) or \fBumount\fP(8) in order to avoid state
>  inconsistencies among administration tools.
> +.PP
> +\fBnilfs_cleanerd\fP displays its process ID (pid) to standard
> +output when it started.
>  .SH OPTIONS
>  .TP
>  \fB\-V\fR, \fB\-\-version\fR
> diff --git a/sbin/cleanerd/cleanerd.c b/sbin/cleanerd/cleanerd.c
> index 86dfcf7..742ab98 100644
> --- a/sbin/cleanerd/cleanerd.c
> +++ b/sbin/cleanerd/cleanerd.c
> @@ -719,6 +719,9 @@ static int daemonize(int nochdir, int noclose)
>  	if (!nochdir && (chdir(ROOTDIR) < 0))
>  		return -1;
>  
> +	printf("NILFS_CLEANERD_PID=%lu\n", (unsigned long)getpid());
> +	fflush(stdout);
> +
>  	if (!noclose) {
>  		close(0);
>  		close(1);
> -- 
> 1.7.9.3
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

      parent reply	other threads:[~2014-01-25 16:46 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-22 13:35 [PATCH] lib/cleaner_exec.c: get process ID of cleanerd through pipe Ryusuke Konishi
     [not found] ` <1390397720-2259-1-git-send-email-konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
2014-01-25 16:46   ` Hitoshi Mitake [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ha8sko1a.wl%mitake.hitoshi@gmail.com \
    --to=mitake.hitoshi-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org \
    --cc=linux-nilfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mitake.hitoshi-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.