contrib/chg/procutil.c
author Jun Wu <quark@fb.com>
Wed, 08 Mar 2017 13:34:25 -0800
changeset 31229 68c94f286e25
parent 30693 baee0f47b533
child 31230 cc37b5a06e32
permissions -rw-r--r--
chg: document why we send SIGHUP and SIGINT to process group This makes the code more consistent - other signals are documented.
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);
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
    57
	if (raise(sig) < 0)  /* resend to self */
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;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   118
	/* 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
   119
	sa.sa_handler = forwardsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   120
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   121
	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
   122
		goto error;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   123
	sa.sa_handler = handlestopsignal;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   124
	sa.sa_flags = SA_RESTART;
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   125
	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
   126
		goto error;
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   127
	/* 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
   128
	sa.sa_handler = handlechildsignal;
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   129
	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
   130
	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
   131
		goto error;
28086
65d24ca35496 chg: forward job control signals to worker process (issue5051)
Yuya Nishihara <yuya@tcha.org>
parents: 28085
diff changeset
   132
28085
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   133
	return;
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   134
c0d1bf1b26b7 chg: verify return value of sigaction() and sigemptyset()
Yuya Nishihara <yuya@tcha.org>
parents: 28084
diff changeset
   135
error:
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   136
	abortmsgerrno("failed to set up signal handlers");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   137
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   138
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
   139
void restoresignalhandler(void)
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   140
{
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   141
	struct sigaction sa;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   142
	memset(&sa, 0, sizeof(sa));
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   143
	sa.sa_handler = SIG_DFL;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   144
	sa.sa_flags = SA_RESTART;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   145
	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
   146
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   147
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   148
	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
   149
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   150
	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
   151
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   152
	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
   153
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   154
	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
   155
		goto error;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   156
	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
   157
		goto error;
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   158
	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
   159
		goto error;
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   160
29370
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   161
	/* 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
   162
	sa.sa_handler = SIG_IGN;
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   163
	if (sigaction(SIGINT, &sa, NULL) < 0)
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   164
		goto error;
3ddf4d0c4170 chg: ignore SIGINT while waiting pager termination
Yuya Nishihara <yuya@tcha.org>
parents: 29369
diff changeset
   165
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   166
	peerpid = 0;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   167
	return;
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   168
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   169
error:
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   170
	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
   171
}
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   172
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   173
/* 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
   174
 * Return 0 if pager is not started, or pid of the pager */
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
   175
pid_t setuppager(const char *pagercmd)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
{
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   177
	assert(pagerpid == 0);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   178
	if (!pagercmd)
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   179
		return 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
	int pipefds[2];
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   182
	if (pipe(pipefds) < 0)
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   183
		return 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   184
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
		goto error;
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   187
	if (pid > 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
		close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
		if (dup2(pipefds[1], fileno(stdout)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
			goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
		if (isatty(fileno(stderr))) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
			if (dup2(pipefds[1], fileno(stderr)) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
				goto error;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
		close(pipefds[1]);
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   196
		pagerpid = pid;
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   197
		return pid;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
	} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
		dup2(pipefds[0], fileno(stdin));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
		close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   201
		close(pipefds[1]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   203
		int r = execlp("/bin/sh", "/bin/sh", "-c", pagercmd, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
		if (r < 0) {
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   205
			abortmsgerrno("cannot start pager '%s'", pagercmd);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   206
		}
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   207
		return 0;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   209
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
error:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
	close(pipefds[0]);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
	close(pipefds[1]);
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   213
	abortmsgerrno("failed to prepare pager");
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   214
	return 0;
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   215
}
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   216
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
   217
void waitpager(void)
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   218
{
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   219
	if (pagerpid == 0)
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   220
		return;
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   221
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   222
	/* 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
   223
	fclose(stdout);
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   224
	fclose(stderr);
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   225
	while (1) {
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   226
		pid_t ret = waitpid(pagerpid, NULL, 0);
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   227
		if (ret == -1 && errno == EINTR)
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   228
			continue;
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   229
		break;
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   230
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   231
}