diff options
author | Eric Wong <e@80x24.org> | 2024-04-26 11:29:44 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2024-04-28 17:05:33 +0000 |
commit | d4529bfbce012361c802a21ce2147ae3967c11eb (patch) | |
tree | 434254c3eb9db0e0624253fb59f1339ebb429f89 /lib/PublicInbox | |
parent | c807cdd1c2e85237e769532a36819888ca97f8b1 (diff) | |
download | public-inbox-d4529bfbce012361c802a21ce2147ae3967c11eb.tar.gz |
alarm(2) delivering SIGALRM seems sufficient for Xapian since Xapian doesn't block signals (which would necessitate the use of SIGKILL via RLIMIT_CPU hard limit). When Xapian gets stuck in `D' state on slow storage, SIGKILL would not make a difference, either (at least not on Linux). Relying on RLIMIT_CPU is also trickier since we must account for CPU time already consumed by a process for unrelated requests. Thus we just rely on a simple alarm-based timeout. This also avoids requiring the optional BSD::Resource module in the (mostly) Perl implementation (and avoids potential bugs given my meager arithmetic skills).
Diffstat (limited to 'lib/PublicInbox')
-rw-r--r-- | lib/PublicInbox/XapHelper.pm | 7 | ||||
-rw-r--r-- | lib/PublicInbox/xap_helper.h | 13 |
2 files changed, 19 insertions, 1 deletions
diff --git a/lib/PublicInbox/XapHelper.pm b/lib/PublicInbox/XapHelper.pm index 746b4d62..2e20660e 100644 --- a/lib/PublicInbox/XapHelper.pm +++ b/lib/PublicInbox/XapHelper.pm @@ -27,6 +27,8 @@ sub cmd_test_inspect { ($req->{srch}->has_threadid ? 1 : 0) } +sub cmd_test_sleep { select(undef, undef, undef, 0.01) while 1 } + sub iter_retry_check ($) { if (ref($@) =~ /\bDatabaseModifiedError\b/) { $_[0]->{srch}->reopen; @@ -193,7 +195,10 @@ sub dispatch { $new->{qp} = $new->qparse_new; $new; }; + my $timeo = $req->{K}; + alarm($timeo) if $timeo; $fn->($req, @argv); + alarm(0) if $timeo; } sub recv_loop { @@ -212,7 +217,7 @@ sub recv_loop { } scalar(@fds) or exit(66); # EX_NOINPUT die "recvmsg: $!" if !defined($fds[0]); - PublicInbox::DS::block_signals(); + PublicInbox::DS::block_signals(POSIX::SIGALRM); my $req = bless {}, __PACKAGE__; my $i = 0; open($req->{$i++}, '+<&=', $_) for @fds; diff --git a/lib/PublicInbox/xap_helper.h b/lib/PublicInbox/xap_helper.h index 7ecea264..3df3ce91 100644 --- a/lib/PublicInbox/xap_helper.h +++ b/lib/PublicInbox/xap_helper.h @@ -27,6 +27,7 @@ #include <sys/types.h> #include <sys/uio.h> #include <sys/wait.h> +#include <poll.h> #include <assert.h> #include <err.h> // BSD, glibc, and musl all have this @@ -413,6 +414,11 @@ static bool cmd_test_inspect(struct req *req) return false; } +static bool cmd_test_sleep(struct req *req) +{ + for (;;) poll(NULL, 0, 10); + return false; +} #include "xh_mset.h" // read-only (WWW, IMAP, lei) stuff #include "xh_cidx.h" // CodeSearchIdx.pm stuff @@ -427,6 +433,7 @@ static const struct cmd_entry { CMD(dump_ibx), // many inboxes CMD(dump_roots), // per-cidx shard CMD(test_inspect), // least common commands last + CMD(test_sleep), // least common commands last }; #define MY_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -680,6 +687,9 @@ static void dispatch(struct req *req) free_srch(kbuf.srch); goto cmd_err; // srch_init already warned } + if (req->timeout_sec) + alarm(req->timeout_sec > UINT_MAX ? + UINT_MAX : (unsigned)req->timeout_sec); try { if (!req->fn(req)) warnx("`%s' failed", req->argv[0]); @@ -688,6 +698,8 @@ static void dispatch(struct req *req) } catch (...) { warn("unhandled exception"); } + if (req->timeout_sec) + alarm(0); cmd_err: return; // just be silent on errors, for now } @@ -1025,6 +1037,7 @@ int main(int argc, char *argv[]) DELSET(SIGXFSZ); #undef DELSET CHECK(int, 0, sigdelset(&workerset, SIGUSR1)); + CHECK(int, 0, sigdelset(&fullset, SIGALRM)); if (nworker == 0) { // no SIGTERM handling w/o workers recv_loop(); |