contrib/chg/procutil.c
author Augie Fackler <augie@google.com>
Fri, 13 Apr 2018 18:28:58 -0400
changeset 37670 719b8cb22936
parent 35959 9724f54923ec
child 41336 763b45bc4483
permissions -rw-r--r--
localrepo: add some overlooked strkwargs love for py3 Differential Revision: https://phab.mercurial-scm.org/D3337
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
/*
30689
9fa7255d4abd chg: move signal and pager handling to a separate file
Jun Wu <quark@fb.com>
parents: 30681
diff changeset
     2
 * Utilities about process handling - signal and subprocess (ex. pager)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
 * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
 * This software may be used and distributed according to the terms of the
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
 * GNU General Public License version 2 or any later version.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     8
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    10
#include <assert.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    11
#include <errno.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    12
#include <signal.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    13
#include <stdio.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    14
#include <string.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    15
#include <sys/wait.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    16
#include <unistd.h>
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    17
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    18
#include "procutil.h"
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    19
#include "util.h"
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    20
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    21
static pid_t pagerpid = 0;
29608
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    22
static pid_t peerpgid = 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
static pid_t peerpid = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
static void forwardsignal(int sig)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
	assert(peerpid > 0);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
	if (kill(peerpid, sig) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    29
		abortmsgerrno("cannot kill %d", peerpid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    30
	debugmsg("forward signal %d", sig);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    31
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
29608
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    33
static void forwardsignaltogroup(int sig)
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    34
{
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    35
	/* prefer kill(-pgid, sig), fallback to pid if pgid is invalid */
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    36
	pid_t killpid = peerpgid > 1 ? -peerpgid : peerpid;
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    37
	if (kill(killpid, sig) < 0)
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    38
		abortmsgerrno("cannot kill %d", killpid);
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    39
	debugmsg("forward signal %d to %d", sig, killpid);
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    40
}
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    41
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    42
static void handlestopsignal(int sig)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    43
{
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    44
	sigset_t unblockset, oldset;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    45
	struct sigaction sa, oldsa;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    46
	if (sigemptyset(&unblockset) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    47
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    48
	if (sigaddset(&unblockset, sig) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    49
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    50
	memset(&sa, 0, sizeof(sa));
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    51
	sa.sa_handler = SIG_DFL;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    52
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    53
	if (sigemptyset(&sa.sa_mask) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    54
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    55
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    56
	forwardsignal(sig);
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
    57
	if (raise(sig) < 0) /* resend to self */
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    58
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    59
	if (sigaction(sig, &sa, &oldsa) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    60
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    61
	if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    62
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    63
	/* resent signal will be handled before sigprocmask() returns */
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    64
	if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    65
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    66
	if (sigaction(sig, &oldsa, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    67
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    68
	return;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    69
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    70
error:
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    71
	abortmsgerrno("failed to handle stop signal");
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    72
}
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    73
29440
009cc6c89d0f chg: silence warning of unused parameter 'sig'
Yuya Nishihara <yuya@tcha.org>
parents: 29429
diff changeset
    74
static void handlechildsignal(int sig UNUSED_)
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    75
{
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    76
	if (peerpid == 0 || pagerpid == 0)
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    77
		return;
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    78
	/* if pager exits, notify the server with SIGPIPE immediately.
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    79
	 * otherwise the server won't get SIGPIPE if it does not write
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    80
	 * anything. (issue5278) */
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    81
	if (waitpid(pagerpid, NULL, WNOHANG) == pagerpid)
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    82
		kill(peerpid, SIGPIPE);
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    83
}
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
    84
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    85
void setupsignalhandler(pid_t pid, pid_t pgid)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    87
	if (pid <= 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    88
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    89
	peerpid = pid;
29608
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    90
	peerpgid = (pgid <= 1 ? 0 : pgid);
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    91
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    92
	struct sigaction sa;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    93
	memset(&sa, 0, sizeof(sa));
31229
68c94f286e25 chg: document why we send SIGHUP and SIGINT to process group
Jun Wu <quark@fb.com>
parents: 30693
diff changeset
    94
68c94f286e25 chg: document why we send SIGHUP and SIGINT to process group
Jun Wu <quark@fb.com>
parents: 30693
diff changeset
    95
	/* deadly signals meant to be sent to a process group:
68c94f286e25 chg: document why we send SIGHUP and SIGINT to process group
Jun Wu <quark@fb.com>
parents: 30693
diff changeset
    96
	 * - SIGHUP: usually generated by the kernel, when termination of a
68c94f286e25 chg: document why we send SIGHUP and SIGINT to process group
Jun Wu <quark@fb.com>
parents: 30693
diff changeset
    97
	 *   process causes that process group to become orphaned
68c94f286e25 chg: document why we send SIGHUP and SIGINT to process group
Jun Wu <quark@fb.com>
parents: 30693
diff changeset
    98
	 * - SIGINT: usually generated by the terminal */
29608
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
    99
	sa.sa_handler = forwardsignaltogroup;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   100
	sa.sa_flags = SA_RESTART;
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   101
	if (sigemptyset(&sa.sa_mask) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   102
		goto error;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   103
	if (sigaction(SIGHUP, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   104
		goto error;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   105
	if (sigaction(SIGINT, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   106
		goto error;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   107
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   108
	/* terminate frontend by double SIGTERM in case of server freeze */
29608
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
   109
	sa.sa_handler = forwardsignal;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   110
	sa.sa_flags |= SA_RESETHAND;
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   111
	if (sigaction(SIGTERM, &sa, NULL) < 0)
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   112
		goto error;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   113
28980
b89e4457fa86 chg: forward SIGWINCH to worker
Jun Wu <quark@fb.com>
parents: 28863
diff changeset
   114
	/* notify the worker about window resize events */
b89e4457fa86 chg: forward SIGWINCH to worker
Jun Wu <quark@fb.com>
parents: 28863
diff changeset
   115
	sa.sa_flags = SA_RESTART;
b89e4457fa86 chg: forward SIGWINCH to worker
Jun Wu <quark@fb.com>
parents: 28863
diff changeset
   116
	if (sigaction(SIGWINCH, &sa, NULL) < 0)
b89e4457fa86 chg: forward SIGWINCH to worker
Jun Wu <quark@fb.com>
parents: 28863
diff changeset
   117
		goto error;
31230
cc37b5a06e32 chg: forward user-defined signals
Jun Wu <quark@fb.com>
parents: 31229
diff changeset
   118
	/* forward user-defined signals */
cc37b5a06e32 chg: forward user-defined signals
Jun Wu <quark@fb.com>
parents: 31229
diff changeset
   119
	if (sigaction(SIGUSR1, &sa, NULL) < 0)
cc37b5a06e32 chg: forward user-defined signals
Jun Wu <quark@fb.com>
parents: 31229
diff changeset
   120
		goto error;
cc37b5a06e32 chg: forward user-defined signals
Jun Wu <quark@fb.com>
parents: 31229
diff changeset
   121
	if (sigaction(SIGUSR2, &sa, NULL) < 0)
cc37b5a06e32 chg: forward user-defined signals
Jun Wu <quark@fb.com>
parents: 31229
diff changeset
   122
		goto error;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   123
	/* propagate job control requests to worker */
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   124
	sa.sa_handler = forwardsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   125
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   126
	if (sigaction(SIGCONT, &sa, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   127
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   128
	sa.sa_handler = handlestopsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   129
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   130
	if (sigaction(SIGTSTP, &sa, NULL) < 0)
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   131
		goto error;
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   132
	/* get notified when pager exits */
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   133
	sa.sa_handler = handlechildsignal;
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   134
	sa.sa_flags = SA_RESTART;
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   135
	if (sigaction(SIGCHLD, &sa, NULL) < 0)
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   136
		goto error;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   137
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   138
	return;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   139
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   140
error:
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   141
	abortmsgerrno("failed to set up signal handlers");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   142
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   143
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
   144
void restoresignalhandler(void)
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   145
{
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   146
	struct sigaction sa;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   147
	memset(&sa, 0, sizeof(sa));
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   148
	sa.sa_handler = SIG_DFL;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   149
	sa.sa_flags = SA_RESTART;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   150
	if (sigemptyset(&sa.sa_mask) < 0)
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   151
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   152
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   153
	if (sigaction(SIGHUP, &sa, NULL) < 0)
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   154
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   155
	if (sigaction(SIGTERM, &sa, NULL) < 0)
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   156
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   157
	if (sigaction(SIGWINCH, &sa, NULL) < 0)
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   158
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   159
	if (sigaction(SIGCONT, &sa, NULL) < 0)
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   160
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   161
	if (sigaction(SIGTSTP, &sa, NULL) < 0)
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   162
		goto error;
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   163
	if (sigaction(SIGCHLD, &sa, NULL) < 0)
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   164
		goto error;
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   165
29370
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   166
	/* ignore Ctrl+C while shutting down to make pager exits cleanly */
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   167
	sa.sa_handler = SIG_IGN;
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   168
	if (sigaction(SIGINT, &sa, NULL) < 0)
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   169
		goto error;
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   170
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   171
	peerpid = 0;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   172
	return;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   173
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   174
error:
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   175
	abortmsgerrno("failed to restore signal handlers");
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   176
}
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   177
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   178
/* This implementation is based on hgext/pager.py (post 369741ef7253)
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   179
 * Return 0 if pager is not started, or pid of the pager */
31941
ac5527021097 chg: respect environment variables for pager
Jun Wu <quark@fb.com>
parents: 31230
diff changeset
   180
pid_t setuppager(const char *pagercmd, const char *envp[])
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
{
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   182
	assert(pagerpid == 0);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   183
	if (!pagercmd)
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   184
		return 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
	int pipefds[2];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
	if (pipe(pipefds) < 0)
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   188
		return 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
		goto error;
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   192
	if (pid > 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
		close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
		if (dup2(pipefds[1], fileno(stdout)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
			goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   196
		if (isatty(fileno(stderr))) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
			if (dup2(pipefds[1], fileno(stderr)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
				goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
		close(pipefds[1]);
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   201
		pagerpid = pid;
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   202
		return pid;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   203
	} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
		dup2(pipefds[0], fileno(stdin));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
		close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
		close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   207
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   208
		int r =
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 31941
diff changeset
   209
		    execle("/bin/sh", "/bin/sh", "-c", pagercmd, NULL, envp);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
		if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   211
			abortmsgerrno("cannot start pager '%s'", pagercmd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
		}
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   213
		return 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   214
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   215
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
error:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
	close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
	close(pipefds[1]);
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   219
	abortmsgerrno("failed to prepare pager");
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   220
	return 0;
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   221
}
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   222
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
   223
void waitpager(void)
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   224
{
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   225
	if (pagerpid == 0)
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   226
		return;
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   227
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   228
	/* close output streams to notify the pager its input ends */
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   229
	fclose(stdout);
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   230
	fclose(stderr);
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   231
	while (1) {
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   232
		pid_t ret = waitpid(pagerpid, NULL, 0);
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   233
		if (ret == -1 && errno == EINTR)
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   234
			continue;
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   235
		break;
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   236
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
}