[master] 59aeb8d Change process to use a pseudo-terminal for stdin/stdout.
Poul-Henning Kamp
phk at FreeBSD.org
Thu Jan 11 10:17:05 UTC 2018
commit 59aeb8dc76e87bd7dbd0706bcc4b329795bce24b
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu Jan 11 10:16:28 2018 +0000
Change process to use a pseudo-terminal for stdin/stdout.
Yes, evil things are afoot.
diff --git a/bin/varnishtest/tests/u00000.vtc b/bin/varnishtest/tests/u00000.vtc
index 8a0ab79..b590e67 100644
--- a/bin/varnishtest/tests/u00000.vtc
+++ b/bin/varnishtest/tests/u00000.vtc
@@ -1,38 +1,33 @@
varnishtest "Simple process tests"
-# new & start
process p1 "cat" -start
-process p2 -log "cat" -start
-process p3 -dump "cat" -start
-process p4 -hexdump "cat" -start
-
-# write
process p1 -writeln "foo"
-process p2 -writeln "bar"
-process p3 -writeln "baz"
-process p4 -writeln "b\001z"
-
-# give enough time for the writes
delay 0.5
-
-# stop
process p1 -stop
-process p2 -close
-process p3 -kill KILL
-process p4 -kill TERM
-
-# wait
process p1 -wait
-process p2 -wait
-process p3 -wait
-process p4 -wait
-
-# check stdout
shell "grep -q foo ${p1_out}"
-shell "grep -q bar ${p2_out}"
-shell "grep -q baz ${p3_out}"
-
-# check stderr
shell "test -f ${p1_err} -a ! -s ${p1_err}"
+
+process p2 -log "cat" -start
+process p2 -writeln "bar"
+delay 0.5
+process p2 -close
+process p2 -wait
+shell "grep -q bar ${p2_out}"
shell "test -f ${p2_err} -a ! -s ${p2_err}"
+
+process p3 -dump "cat" -start
+process p3 -writeln "baz"
+delay 0.5
+process p3 -kill KILL
+process p3 -wait
+shell "grep -q baz ${p3_out}"
shell "test -f ${p3_err} -a ! -s ${p3_err}"
+
+process p4 -hexdump "cat" -start
+process p4 -writeln "b\001z"
+delay 0.5
+process p4 -kill TERM
+process p4 -wait
+
+process p5 -log "stty -a ; sleep 1" -run
diff --git a/bin/varnishtest/vtc_process.c b/bin/varnishtest/vtc_process.c
index bde9e98..f6a8bdb 100644
--- a/bin/varnishtest/vtc_process.c
+++ b/bin/varnishtest/vtc_process.c
@@ -28,6 +28,7 @@
#include "config.h"
+#include <sys/ioctl.h> // Linux: struct winsize
#include <sys/resource.h>
#include <sys/wait.h>
@@ -37,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
#include "vtc.h"
@@ -57,14 +59,12 @@ struct process {
char *dir;
char *out;
char *err;
- int fd_stdin;
- int fd_stdout;
+ int fd_term;
int fd_stderr;
int f_stdout;
int f_stderr;
struct vlu *vlu_stdout;
struct vlu *vlu_stderr;
- const char *cur_fd;
int log;
pid_t pid;
int expect_exit;
@@ -107,15 +107,14 @@ process_new(const char *name)
AN(p->vl);
PROCESS_EXPAND(dir, "${tmpdir}/%s", name);
- PROCESS_EXPAND(out, "${tmpdir}/%s/stdout", name);
+ PROCESS_EXPAND(out, "${tmpdir}/%s/term", name);
PROCESS_EXPAND(err, "${tmpdir}/%s/stderr", name);
bprintf(buf, "rm -rf %s ; mkdir -p %s ; touch %s %s",
p->dir, p->dir, p->out, p->err);
AZ(system(buf));
- p->fd_stdin = -1;
- p->fd_stdout = -1;
+ p->fd_term = -1;
VTAILQ_INSERT_TAIL(&processes, p, list);
return (p);
@@ -169,7 +168,7 @@ process_vlu_func(void *priv, const char *l)
struct process *p;
CAST_OBJ_NOTNULL(p, priv, PROCESS_MAGIC);
- vtc_dump(p->vl, 4, p->cur_fd, l, -1);
+ vtc_dump(p->vl, 4, "output", l, -1);
return (0);
}
@@ -182,8 +181,7 @@ process_stdout(const struct vev *ev, int what)
CAST_OBJ_NOTNULL(p, ev->priv, PROCESS_MAGIC);
(void)what;
- p->cur_fd = "stdout";
- i = read(p->fd_stdout, buf, sizeof buf);
+ i = read(p->fd_term, buf, sizeof buf);
if (i <= 0) {
vtc_log(p->vl, 4, "stdout read %d", i);
return (1);
@@ -207,18 +205,12 @@ process_stderr(const struct vev *ev, int what)
CAST_OBJ_NOTNULL(p, ev->priv, PROCESS_MAGIC);
(void)what;
- p->cur_fd = "stderr";
i = read(p->fd_stderr, buf, sizeof buf);
if (i <= 0) {
vtc_log(p->vl, 4, "stderr read %d", i);
return (1);
}
- if (p->log == 1)
- (void)VLU_Feed(p->vlu_stderr, buf, i);
- else if (p->log == 2)
- vtc_dump(p->vl, 4, "stderr", buf, i);
- else if (p->log == 3)
- vtc_hexdump(p->vl, 4, "stderr", buf, i);
+ vtc_dump(p->vl, 4, "stderr", buf, i);
(void)write(p->f_stderr, buf, i);
return (0);
}
@@ -244,7 +236,7 @@ process_thread(void *priv)
ev = VEV_Alloc();
AN(ev);
- ev->fd = p->fd_stdout;
+ ev->fd = p->fd_term;
ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
ev->callback = process_stdout;
ev->priv = p;
@@ -313,10 +305,40 @@ process_thread(void *priv)
}
static void
+process_init_term(int fd)
+{
+ struct winsize ws;
+ struct termios tt;
+
+ memset(&ws, 0, sizeof ws);
+ ws.ws_row = 24;
+ ws.ws_col = 80;
+ AZ(ioctl(fd, TIOCSWINSZ, &ws));
+
+ memset(&tt, 0, sizeof tt);
+ tt.c_cflag = CREAD | CS8 | HUPCL;
+ tt.c_iflag = BRKINT | ICRNL | IMAXBEL | IXON | IXANY;
+ tt.c_lflag = ICANON | ISIG | IEXTEN;
+ tt.c_oflag = OPOST | ONLCR;
+ tt.c_ispeed = B9600;
+ tt.c_ospeed = B9600;
+ tt.c_cc[VEOF] = '\x04'; // CTRL-D
+ tt.c_cc[VERASE] = '\x08'; // CTRL-H (Backspace)
+ tt.c_cc[VKILL] = '\x15'; // CTRL-U
+ tt.c_cc[VINTR] = '\x03'; // CTRL-C
+ tt.c_cc[VQUIT] = '\x1c'; // CTRL-backslash
+ tt.c_cc[VMIN] = 1;
+
+ AZ(tcsetattr(fd, TCSAFLUSH, &tt));
+}
+
+static void
process_start(struct process *p)
{
struct vsb *cl;
- int fd0[2], fd1[2], fd2[2];
+ int fd2[2];
+ int master, slave;
+ const char *slavename;
CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
if (p->hasthread)
@@ -327,15 +349,25 @@ process_start(struct process *p)
cl = macro_expand(p->vl, p->spec);
AN(cl);
- AZ(pipe(fd0));
- AZ(pipe(fd1));
+ master = posix_openpt(O_RDWR|O_NOCTTY);
+ assert(master >= 0);
+ AZ(grantpt(master));
+ AZ(unlockpt(master));
+ slavename = ptsname(master);
+ AN(slavename);
+ slave = open(slavename, O_RDWR);
+ assert(slave >= 0);
+
+ process_init_term(slave);
+
AZ(pipe(fd2));
p->pid = fork();
assert(p->pid >= 0);
if (p->pid == 0) {
- assert(dup2(fd0[0], STDIN_FILENO) == STDIN_FILENO);
- assert(dup2(fd1[1], STDOUT_FILENO) == STDOUT_FILENO);
+ setenv("TERM", "adm3a", 1);
+ assert(dup2(slave, STDIN_FILENO) == STDIN_FILENO);
+ assert(dup2(slave, STDOUT_FILENO) == STDOUT_FILENO);
assert(dup2(fd2[1], STDERR_FILENO) == STDERR_FILENO);
VSUB_closefrom(STDERR_FILENO + 1);
AZ(setpgid(0, 0));
@@ -346,11 +378,9 @@ process_start(struct process *p)
vtc_log(p->vl, 3, "PID: %ld", (long)p->pid);
VSB_destroy(&cl);
- closefd(&fd0[0]);
- closefd(&fd1[1]);
+ closefd(&slave);
+ p->fd_term = master;
closefd(&fd2[1]);
- p->fd_stdin = fd0[1];
- p->fd_stdout = fd1[0];
p->fd_stderr = fd2[0];
macro_def(p->vl, p->name, "pid", "%ld", (long)p->pid);
macro_def(p->vl, p->name, "dir", "%s", p->dir);
@@ -401,6 +431,8 @@ process_kill(struct process *p, const char *sig)
j = SIGINT;
else if (!strcmp(sig, "KILL"))
j = SIGKILL;
+ else if (!strcmp(sig, "HUP"))
+ j = SIGHUP;
else if (*sig == '-')
j = strtoul(sig + 1, NULL, 10);
else
@@ -427,7 +459,7 @@ process_write(const struct process *p, const char *text)
len = strlen(text);
vtc_log(p->vl, 4, "Writing %d bytes", len);
- r = write(p->fd_stdin, text, len);
+ r = write(p->fd_term, text, len);
if (r < 0)
vtc_fatal(p->vl, "Failed to write: %s (%d)",
strerror(errno), errno);
@@ -440,16 +472,22 @@ process_close(struct process *p)
if (!p->hasthread)
vtc_fatal(p->vl, "Cannot close a non-running process");
- AZ(pthread_mutex_lock(&p->mtx));
- if (p->fd_stdin >= 0)
- closefd(&p->fd_stdin);
- AZ(pthread_mutex_unlock(&p->mtx));
+ process_kill(p, "HUP");
}
/* SECTION: process process
*
- * Run a process in the background with stdout and stderr redirected to
- * ${pNAME_out} and ${pNAME_err}, both located in ${pNAME_dir}::
+ * Run a process with stdin+stdout on a pseudo-terminal and stderr on a pipe.
+ *
+ * Output from the pseudo-terminal is copied verbatim to ${pNAME_out},
+ * and the -log/-dump/-hexdump flags will also put it in the vtc-log.
+ *
+ * The pseudo-terminal is not in ECHO mode, but if the programs run set
+ * it to ECHO mode ("stty sane") any input sent to the process will also
+ * appear in this stream because of the ECHO.
+ *
+ * Output from the stderr-pipe is copied verbatim to ${pNAME_err}, and
+ * is always included in the vtc_log.
*
* process pNAME SPEC [-log] [-dump] [-hexdump] [-expect-exit N]
* [-start] [-run]
@@ -463,13 +501,13 @@ process_close(struct process *p)
* The command(s) to run in this process.
*
* \-hexdump
- * Log stdout/stderr with vtc_hexdump(). Must be before -start/-run.
+ * Log output with vtc_hexdump(). Must be before -start/-run.
*
* \-dump
- * Log stdout/stderr with vtc_dump(). Must be before -start/-run.
+ * Log output with vtc_dump(). Must be before -start/-run.
*
* \-log
- * Log stdout/stderr with VLU/vtc_log(). Must be before -start/-run.
+ * Log output with VLU/vtc_log(). Must be before -start/-run.
*
* \-start
* Start the process.
@@ -520,7 +558,7 @@ process_close(struct process *p)
* Same as -write followed by a newline (\\n).
*
* \-close
- * Close the process' stdin.
+ * Alias for "-kill HUP"
*
*/
More information about the varnish-commit
mailing list