[i-g-t PATCH 1/4] lib/igt_core: Add igt_exec helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Support executing external processes with the goal of capturing its
standard streams to the igt logging infrastructure in addition to its
exit status.

Cc: Daniel Vetter <daniel.vetter@xxxxxxxx>
Cc: Petri Latvala <petri.latvala@xxxxxxxxx>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@xxxxxxxxxxxxxxx>
---
 lib/igt_core.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_core.h |   3 ++
 2 files changed, 154 insertions(+)

diff --git a/lib/igt_core.c b/lib/igt_core.c
index 403b942..8a7ba0d 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -2073,3 +2073,154 @@ 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)
+{
+	int fds[2], flags;
+
+	if (pipe(fds) == -1)
+		return false;
+
+	if ((flags = fcntl(fds[0], F_GETFL) == -1))
+		return false;
+
+	flags |= O_NONBLOCK;
+	if (fcntl(fds[0], F_SETFL, flags) == -1)
+		return false;
+
+	/* save output */
+	if ((p->save_fd = dup(output_fd)) == -1)
+		return false;
+
+	/* Redirect output to our buffer */
+	if (dup2(fds[1], output_fd) == -1)
+		return false;
+
+	p->output_fd = output_fd;
+	p->read_fd = fds[0];
+	p->write_fd = fds[1];
+	p->redirected = true;
+	p->log_level = level;
+
+	return true;
+}
+
+static bool unredirect_output(struct output_pipe *p)
+{
+	close(p->write_fd);
+	if (dup2(p->save_fd, p->output_fd) == -1)
+		return false;
+	close(p->save_fd);
+
+	p->redirected = false;
+
+	return true;
+}
+
+/**
+ * igt_exec:
+ *
+ * Executes the shell command specified in @command and capture its stdout and
+ * stderr to igt_log or igt_warn respectively.
+ *
+ * Returns: The exit status of the executed process. -1 for failure.
+ */
+int igt_exec(const char *command)
+{
+#define OUT 0
+#define ERR 1
+	struct output_pipe op[2];
+	int i, sel_fd, status;
+	fd_set fds;
+	struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
+	char buf[PIPE_BUF];
+
+	if (!redirect_output(&op[OUT], STDOUT_FILENO, IGT_LOG_INFO))
+		return -1;
+	if (!redirect_output(&op[ERR], STDERR_FILENO, IGT_LOG_WARN))
+		return -1;
+
+	if ((status = system(command)) == -1)
+		return -1;
+
+	FD_ZERO(&fds);
+	FD_SET(op[OUT].read_fd, &fds);
+	FD_SET(op[ERR].read_fd, &fds);
+
+	sel_fd = max(op[OUT].read_fd, op[ERR].read_fd);
+	if (select(sel_fd + 1, &fds, NULL, NULL, &timeout) == -1)
+		return -1;
+
+	for (i = 0; i < ARRAY_SIZE(op); i++) {
+		struct output_pipe *current = &op[i];
+
+		if (!FD_ISSET(current->read_fd, &fds)) {
+			close(current->read_fd);
+			if (!unredirect_output(current))
+				return -1;
+			continue;
+		}
+
+		memset(buf, 0, sizeof(buf));
+		while (read(current->read_fd, buf, sizeof(buf)) > 0) {
+			if (current->redirected) {
+				if (!unredirect_output(current))
+					return -1;
+			}
+			igt_log(IGT_LOG_DOMAIN, current->log_level,
+				"[cmd] %s", buf);
+			memset(buf, 0, sizeof(buf));
+		}
+		close(current->read_fd);
+	}
+
+	return WEXITSTATUS(status);
+}
+
+/**
+ * igt_exec_quiet:
+ * Similar to igt_exec(), except redirect output to /dev/null
+ *
+ * Returns: The exit status of the executed process. -1 for failure.
+ */
+int igt_exec_quiet(const char *command)
+{
+	int stderr_fd_copy, stdout_fd_copy, status, nullfd;
+
+	/* redirect */
+	if ((nullfd = open("/dev/null", O_WRONLY)) == -1)
+		return -1;
+	if ((stdout_fd_copy = dup(STDOUT_FILENO)) == -1)
+		return -1;
+	if ((stderr_fd_copy = dup(STDERR_FILENO)) == -1)
+		return -1;
+
+	if (dup2(nullfd, STDOUT_FILENO) == -1)
+		return -1;
+	if (dup2(nullfd, STDERR_FILENO) == -1)
+		return -1;
+
+	if ((status = system(command)) == -1)
+		return -1;
+
+	/* restore */
+	if (dup2(stdout_fd_copy, STDOUT_FILENO) == -1)
+		return -1;
+	if (dup2(stderr_fd_copy, STDERR_FILENO) == -1)
+		return -1;
+
+	close(stdout_fd_copy);
+	close(stderr_fd_copy);
+
+	return WEXITSTATUS(status);
+}
diff --git a/lib/igt_core.h b/lib/igt_core.h
index 51b98d8..6d4cf60 100644
--- a/lib/igt_core.h
+++ b/lib/igt_core.h
@@ -918,4 +918,7 @@ FILE *__igt_fopen_data(const char* igt_srcdir, const char* igt_datadir,
 #define igt_fopen_data(filename) \
 	__igt_fopen_data(IGT_SRCDIR, IGT_DATADIR, filename)
 
+int igt_exec(const char *command);
+int igt_exec_quiet(const char *command);
+
 #endif /* IGT_CORE_H */
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux