[Intel-gfx] [PATCH i-g-t 2/2] igt_core: Rework igt_system()

Abdiel Janulgue abdiel.janulgue at linux.intel.com
Mon Sep 25 08:33:51 UTC 2017



On 09/21/2017 03:52 PM, Petri Latvala wrote:
> Instead of redirecting output to pipes and forking, redirect after
> forking to avoid having to carefully unredirect before logging
> anything.
> 
> igt at tools_test@sysfs_l3_parity had a racy condition where it prints
> the output of intel_l3_parity prepended by [cmd], but that ended up
> being printed again prepended by [cmd] because output was redirected,
> causing outputs to appear multiple times. This patch fixes that.
> 
> CC: Abdiel Janulgue <abdiel.janulgue at linux.intel.com>
> Signed-off-by: Petri Latvala <petri.latvala at intel.com>

Thanks for fixing this. Series is
Reviewed-by: Abdiel Janulgue <abdiel.janulgue at linux.intel.com>

> ---
>  lib/igt_core.c | 115 ++++++++++++++++++++-------------------------------------
>  1 file changed, 40 insertions(+), 75 deletions(-)
> 
> diff --git a/lib/igt_core.c b/lib/igt_core.c
> index 9f4ee68b..47b4682d 100644
> --- a/lib/igt_core.c
> +++ b/lib/igt_core.c
> @@ -2237,58 +2237,23 @@ FILE *__igt_fopen_data(const char* igt_srcdir, const char* igt_datadir,
>  	return fp;
>  }
>  
> -struct output_pipe {
> -	int output_fd;
> -	int save_fd;
> -	int read_fd;
> -	int write_fd;
> -	bool redirected;
> -	enum igt_log_level log_level;
> -};
> -
> -static bool redirect_output(struct output_pipe *p, int output_fd,
> -			    enum igt_log_level level)
> +static void log_output(int *fd, enum igt_log_level level)
>  {
> -	int fds[2];
> -
> -	if (pipe(fds) == -1)
> -		goto err;
> -
> -	/* save output */
> -	if ((p->save_fd = dup(output_fd)) == -1)
> -		goto err;
> -
> -	/* Redirect output to our buffer */
> -	if (dup2(fds[1], output_fd) == -1)
> -		goto err;
> -
> -	p->output_fd = output_fd;
> -	p->read_fd = fds[0];
> -	p->write_fd = fds[1];
> -	p->redirected = true;
> -	p->log_level = level;
> -
> -	return true;
> -err:
> -	close(fds[0]);
> -	close(fds[1]);
> -	close(p->save_fd);
> +	ssize_t len;
> +	char buf[PIPE_BUF];
>  
> -	return false;
> -}
> +	if (*fd < 0)
> +		return;
>  
> -static void unredirect_output(struct output_pipe *p)
> -{
> -	if (!p->redirected)
> +	memset(buf, 0, sizeof(buf));
> +	len = read(*fd, buf, sizeof(buf));
> +	if (len <= 0) {
> +		close(*fd);
> +		*fd = -1;
>  		return;
> +	}
>  
> -	/* read_fd is closed separately. We still need to read its
> -	 * buffered contents after un-redirecting the stream.
> -	 */
> -	close(p->write_fd);
> -	dup2(p->save_fd, p->output_fd);
> -	close(p->save_fd);
> -	p->redirected = false;
> +	igt_log(IGT_LOG_DOMAIN, level, "[cmd] %s", buf);
>  }
>  
>  /**
> @@ -2304,48 +2269,48 @@ static void unredirect_output(struct output_pipe *p)
>   */
>  int igt_system(const char *command)
>  {
> -#define OUT 0
> -#define ERR 1
> -	struct output_pipe op[2];
> -	int i, status;
> +	int outpipe[2] = { -1, -1 };
> +	int errpipe[2] = { -1, -1 };
> +	int status;
>  	struct igt_helper_process process = {};
> -	char buf[PIPE_BUF];
>  
> -	if (!redirect_output(&op[OUT], STDOUT_FILENO, IGT_LOG_INFO))
> +	if (pipe(outpipe) < 0)
>  		goto err;
> -	if (!redirect_output(&op[ERR], STDERR_FILENO, IGT_LOG_WARN))
> +	if (pipe(errpipe) < 0)
>  		goto err;
>  
>  	igt_fork_helper(&process) {
> -		igt_assert(execl("/bin/sh", "sh", "-c", command,
> -				 (char *) NULL) != -1);
> +		close(outpipe[0]);
> +		close(errpipe[0]);
> +
> +		if (dup2(outpipe[1], STDOUT_FILENO) < 0)
> +			goto child_err;
> +		if (dup2(errpipe[1], STDERR_FILENO) < 0)
> +			goto child_err;
> +
> +		execl("/bin/sh", "sh", "-c", command,
> +		      (char *) NULL);
> +
> +	child_err:
> +		exit(EXIT_FAILURE);
>  	}
>  
> -	for (i = 0; i < ARRAY_SIZE(op); i++) {
> -		struct output_pipe *current = &op[i];
> +	close(outpipe[1]);
> +	close(errpipe[1]);
>  
> -		/* Unredirect so igt_log() works */
> -		unredirect_output(current);
> -		memset(buf, 0, sizeof(buf));
> -		while (read(current->read_fd, buf, sizeof(buf)) > 0) {
> -			igt_log(IGT_LOG_DOMAIN, current->log_level,
> -				"[cmd] %s", buf);
> -			memset(buf, 0, sizeof(buf));
> -		}
> -		close(current->read_fd);
> +	while (outpipe[0] >= 0 || errpipe[0] >= 0) {
> +		log_output(&outpipe[0], IGT_LOG_INFO);
> +		log_output(&errpipe[0], IGT_LOG_WARN);
>  	}
> +
>  	status = igt_wait_helper(&process);
>  
>  	return WEXITSTATUS(status);
>  err:
> -	/* Failed to redirect one or both streams. Roll back changes. */
> -	for (i = 0; i < ARRAY_SIZE(op); i++) {
> -		if (!op[i].redirected)
> -			continue;
> -		close(op[i].read_fd);
> -		unredirect_output(&op[i]);
> -	}
> -
> +	close(outpipe[0]);
> +	close(outpipe[1]);
> +	close(errpipe[0]);
> +	close(errpipe[1]);
>  	return -1;
>  }
>  
> 


More information about the Intel-gfx mailing list