##// END OF EJS Templates
rhg: parallellize computation of [unsure_is_modified]...
rhg: parallellize computation of [unsure_is_modified] [unsure_is_modified] is called for every file for which we can't determine its status based on its size and mtime alone. In particular, this happens if the mtime of the file changes without its contents changing. Parallellizing this improves performance significantly when we have many of these files. Here's an example run (on a repo with ~400k files after dropping FS caches) ``` before: real 0m53.901s user 0m27.806s sys 0m31.325s after: real 0m32.017s user 0m34.277s sys 1m26.250s ``` Another example run (a different FS): ``` before: real 3m28.479s user 0m31.800s sys 0m25.324s after: real 0m29.751s user 0m41.814s sys 1m15.387s ```

File last commit:

r41367:763b45bc default
r50412:52464a20 default
Show More
sighandlers.c
175 lines | 3.7 KiB | text/x-c | CLexer
/*
* Signal handlers for cHg
*
* Copyright 2011, 2018 Yuya Nishihara <yuya@tcha.org>
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2 or any later version.
*/
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
static pid_t peerpgid = 0;
static pid_t peerpid = 0;
static void forwardsignal(int sig)
{
assert(peerpid > 0);
(void)kill(peerpid, sig);
}
static void forwardsignaltogroup(int sig)
{
/* prefer kill(-pgid, sig), fallback to pid if pgid is invalid */
pid_t killpid = peerpgid > 1 ? -peerpgid : peerpid;
(void)kill(killpid, sig);
}
static void handlestopsignal(int sig)
{
sigset_t unblockset, oldset;
struct sigaction sa, oldsa;
if (sigemptyset(&unblockset) < 0) {
return;
}
if (sigaddset(&unblockset, sig) < 0) {
return;
}
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
if (sigemptyset(&sa.sa_mask) < 0) {
return;
}
forwardsignal(sig);
if (raise(sig) < 0) { /* resend to self */
return;
}
if (sigaction(sig, &sa, &oldsa) < 0) {
return;
}
if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0) {
return;
}
/* resent signal will be handled before sigprocmask() returns */
if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) {
return;
}
if (sigaction(sig, &oldsa, NULL) < 0) {
return;
}
}
/*
* Installs signal handlers.
*
* Returns 0 on success, -1 on error and errno is set appropriately.
* Installed handlers wouldn't be cleaned up on error.
*/
int setupsignalhandler(pid_t pid, pid_t pgid)
{
if (pid <= 0) {
errno = EINVAL;
return -1;
}
peerpid = pid;
peerpgid = (pgid <= 1 ? 0 : pgid);
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
/* deadly signals meant to be sent to a process group:
* - SIGHUP: usually generated by the kernel, when termination of a
* process causes that process group to become orphaned
* - SIGINT: usually generated by the terminal */
sa.sa_handler = forwardsignaltogroup;
sa.sa_flags = SA_RESTART;
if (sigemptyset(&sa.sa_mask) < 0) {
return -1;
}
if (sigaction(SIGHUP, &sa, NULL) < 0) {
return -1;
}
if (sigaction(SIGINT, &sa, NULL) < 0) {
return -1;
}
/* terminate frontend by double SIGTERM in case of server freeze */
sa.sa_handler = forwardsignal;
sa.sa_flags |= SA_RESETHAND;
if (sigaction(SIGTERM, &sa, NULL) < 0) {
return -1;
}
/* notify the worker about window resize events */
sa.sa_flags = SA_RESTART;
if (sigaction(SIGWINCH, &sa, NULL) < 0) {
return -1;
}
/* forward user-defined signals */
if (sigaction(SIGUSR1, &sa, NULL) < 0) {
return -1;
}
if (sigaction(SIGUSR2, &sa, NULL) < 0) {
return -1;
}
/* propagate job control requests to worker */
sa.sa_handler = forwardsignal;
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCONT, &sa, NULL) < 0) {
return -1;
}
sa.sa_handler = handlestopsignal;
sa.sa_flags = SA_RESTART;
if (sigaction(SIGTSTP, &sa, NULL) < 0) {
return -1;
}
return 0;
}
/*
* Restores signal handlers to the default, and masks SIGINT.
*
* Returns 0 on success, -1 on error and errno is set appropriately.
*/
int restoresignalhandler(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
if (sigemptyset(&sa.sa_mask) < 0) {
return -1;
}
if (sigaction(SIGHUP, &sa, NULL) < 0) {
return -1;
}
if (sigaction(SIGTERM, &sa, NULL) < 0) {
return -1;
}
if (sigaction(SIGWINCH, &sa, NULL) < 0) {
return -1;
}
if (sigaction(SIGCONT, &sa, NULL) < 0) {
return -1;
}
if (sigaction(SIGTSTP, &sa, NULL) < 0) {
return -1;
}
/* ignore Ctrl+C while shutting down to make pager exits cleanly */
sa.sa_handler = SIG_IGN;
if (sigaction(SIGINT, &sa, NULL) < 0) {
return -1;
}
peerpid = 0;
return 0;
}