mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Add a -D flag to ask tmux not to daemonize, useful both for running a
debugger (lldb does not have follow-fork-mode) and for running with a managed supervisor init system. GitHub issue 2190.
This commit is contained in:
parent
126bacb473
commit
dceb6a15d0
9
proc.c
9
proc.c
@ -37,6 +37,7 @@ struct tmuxproc {
|
||||
|
||||
void (*signalcb)(int);
|
||||
|
||||
struct event ev_sigint;
|
||||
struct event ev_sighup;
|
||||
struct event ev_sigchld;
|
||||
struct event ev_sigcont;
|
||||
@ -221,10 +222,13 @@ proc_set_signals(struct tmuxproc *tp, void (*signalcb)(int))
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
sigaction(SIGTSTP, &sa, NULL);
|
||||
sigaction(SIGTTIN, &sa, NULL);
|
||||
sigaction(SIGTTOU, &sa, NULL);
|
||||
|
||||
signal_set(&tp->ev_sigint, SIGINT, proc_signal_cb, tp);
|
||||
signal_add(&tp->ev_sigint, NULL);
|
||||
signal_set(&tp->ev_sighup, SIGHUP, proc_signal_cb, tp);
|
||||
signal_add(&tp->ev_sighup, NULL);
|
||||
signal_set(&tp->ev_sigchld, SIGCHLD, proc_signal_cb, tp);
|
||||
@ -251,10 +255,10 @@ proc_clear_signals(struct tmuxproc *tp, int defaults)
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
sigaction(SIGTSTP, &sa, NULL);
|
||||
|
||||
signal_del(&tp->ev_sigint);
|
||||
signal_del(&tp->ev_sighup);
|
||||
signal_del(&tp->ev_sigchld);
|
||||
signal_del(&tp->ev_sigcont);
|
||||
@ -264,6 +268,7 @@ proc_clear_signals(struct tmuxproc *tp, int defaults)
|
||||
signal_del(&tp->ev_sigwinch);
|
||||
|
||||
if (defaults) {
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
sigaction(SIGCONT, &sa, NULL);
|
||||
|
@ -238,11 +238,22 @@ server_client_create(int fd)
|
||||
int
|
||||
server_client_open(struct client *c, char **cause)
|
||||
{
|
||||
const char *ttynam = _PATH_TTY;
|
||||
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
return (0);
|
||||
|
||||
if (strcmp(c->ttyname, "/dev/tty") == 0) {
|
||||
*cause = xstrdup("can't use /dev/tty");
|
||||
if (strcmp(c->ttyname, ttynam) == 0||
|
||||
((isatty(STDIN_FILENO) &&
|
||||
(ttynam = ttyname(STDIN_FILENO)) != NULL &&
|
||||
strcmp(c->ttyname, ttynam) == 0) ||
|
||||
(isatty(STDOUT_FILENO) &&
|
||||
(ttynam = ttyname(STDOUT_FILENO)) != NULL &&
|
||||
strcmp(c->ttyname, ttynam) == 0) ||
|
||||
(isatty(STDERR_FILENO) &&
|
||||
(ttynam = ttyname(STDERR_FILENO)) != NULL &&
|
||||
strcmp(c->ttyname, ttynam) == 0))) {
|
||||
xasprintf(cause, "can't use %s", c->ttyname);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
44
server.c
44
server.c
@ -161,29 +161,35 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
|
||||
struct client *c;
|
||||
char *cause = NULL;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
|
||||
fatal("socketpair failed");
|
||||
server_client_flags = flags;
|
||||
|
||||
sigfillset(&set);
|
||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
fatal("fork failed");
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
close(pair[1]);
|
||||
return (pair[0]);
|
||||
|
||||
if (~flags & CLIENT_NOFORK) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
|
||||
fatal("socketpair failed");
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
fatal("fork failed");
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
close(pair[1]);
|
||||
return (pair[0]);
|
||||
}
|
||||
close(pair[0]);
|
||||
if (daemon(1, 0) != 0)
|
||||
fatal("daemon failed");
|
||||
}
|
||||
close(pair[0]);
|
||||
if (daemon(1, 0) != 0)
|
||||
fatal("daemon failed");
|
||||
|
||||
server_client_flags = flags;
|
||||
proc_clear_signals(client, 0);
|
||||
|
||||
if (event_reinit(base) != 0)
|
||||
fatalx("event_reinit failed");
|
||||
server_proc = proc_start("server");
|
||||
|
||||
proc_set_signals(server_proc, server_signal);
|
||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||
|
||||
@ -205,7 +211,10 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
|
||||
server_fd = server_create_socket(flags, &cause);
|
||||
if (server_fd != -1)
|
||||
server_update_socket();
|
||||
c = server_client_create(pair[1]);
|
||||
if (~flags & CLIENT_NOFORK)
|
||||
c = server_client_create(pair[1]);
|
||||
else
|
||||
options_set_number(global_options, "exit-empty", 0);
|
||||
|
||||
if (lockfd >= 0) {
|
||||
unlink(lockfile);
|
||||
@ -396,6 +405,7 @@ server_signal(int sig)
|
||||
|
||||
log_debug("%s: %s", __func__, strsignal(sig));
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
server_exit = 1;
|
||||
server_send_exit();
|
||||
|
13
tmux.1
13
tmux.1
@ -23,7 +23,7 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm tmux
|
||||
.Bk -words
|
||||
.Op Fl 2CluvV
|
||||
.Op Fl 2CDluvV
|
||||
.Op Fl c Ar shell-command
|
||||
.Op Fl f Ar file
|
||||
.Op Fl L Ar socket-name
|
||||
@ -122,6 +122,17 @@ This option is for compatibility with
|
||||
when
|
||||
.Nm
|
||||
is used as a login shell.
|
||||
.It Fl D
|
||||
Do not start the
|
||||
.Nm
|
||||
server as a daemon.
|
||||
This also turns the
|
||||
.Ic exit-empty
|
||||
option off.
|
||||
With
|
||||
.Fl D ,
|
||||
.Ar command
|
||||
may not be specified.
|
||||
.It Fl f Ar file
|
||||
Specify an alternative configuration file.
|
||||
By default,
|
||||
|
9
tmux.c
9
tmux.c
@ -57,7 +57,7 @@ static __dead void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n"
|
||||
"usage: %s [-2CDluvV] [-c shell-command] [-f file] [-L socket-name]\n"
|
||||
" [-S socket-path] [-T features] [command [flags]]\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
@ -336,7 +336,7 @@ main(int argc, char **argv)
|
||||
if (**argv == '-')
|
||||
flags = CLIENT_LOGIN;
|
||||
|
||||
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:T:uUvV")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "2c:CDdf:lL:qS:T:uUvV")) != -1) {
|
||||
switch (opt) {
|
||||
case '2':
|
||||
tty_add_features(&feat, "256", ":,");
|
||||
@ -344,6 +344,9 @@ main(int argc, char **argv)
|
||||
case 'c':
|
||||
shell_command = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
flags |= CLIENT_NOFORK;
|
||||
break;
|
||||
case 'C':
|
||||
if (flags & CLIENT_CONTROL)
|
||||
flags |= CLIENT_CONTROLCONTROL;
|
||||
@ -387,6 +390,8 @@ main(int argc, char **argv)
|
||||
|
||||
if (shell_command != NULL && argc != 0)
|
||||
usage();
|
||||
if ((flags & CLIENT_NOFORK) && argc != 0)
|
||||
usage();
|
||||
|
||||
if ((ptm_fd = getptmfd()) == -1)
|
||||
err(1, "getptmfd");
|
||||
|
1
tmux.h
1
tmux.h
@ -1584,6 +1584,7 @@ struct client {
|
||||
#define CLIENT_DEFAULTSOCKET 0x8000000
|
||||
#define CLIENT_STARTSERVER 0x10000000
|
||||
#define CLIENT_REDRAWPANES 0x20000000
|
||||
#define CLIENT_NOFORK 0x40000000
|
||||
#define CLIENT_ALLREDRAWFLAGS \
|
||||
(CLIENT_REDRAWWINDOW| \
|
||||
CLIENT_REDRAWSTATUS| \
|
||||
|
7
tty.c
7
tty.c
@ -154,16 +154,21 @@ tty_read_callback(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct tty *tty = data;
|
||||
struct client *c = tty->client;
|
||||
const char *name = c->name;
|
||||
size_t size = EVBUFFER_LENGTH(tty->in);
|
||||
int nread;
|
||||
|
||||
nread = evbuffer_read(tty->in, tty->fd, -1);
|
||||
if (nread == 0 || nread == -1) {
|
||||
if (nread == 0)
|
||||
log_debug("%s: read closed", name);
|
||||
else
|
||||
log_debug("%s: read error: %s", name, strerror(errno));
|
||||
event_del(&tty->event_in);
|
||||
server_client_lost(tty->client);
|
||||
return;
|
||||
}
|
||||
log_debug("%s: read %d bytes (already %zu)", c->name, nread, size);
|
||||
log_debug("%s: read %d bytes (already %zu)", name, nread, size);
|
||||
|
||||
while (tty_keys_next(tty))
|
||||
;
|
||||
|
Loading…
Reference in New Issue
Block a user