diff options
author | Eric Wong <e@80x24.org> | 2023-08-30 05:10:44 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2023-08-30 05:27:36 +0000 |
commit | 1bc05a93b7a7259fece20655e65220cdc05cce5d (patch) | |
tree | f14c3fba8349e3228ee9c9a591768fb709c31074 /lib/PublicInbox/xap_helper.h | |
parent | b78cd406ff28d8c25081dd81072c362c001bad5b (diff) | |
download | public-inbox-1bc05a93b7a7259fece20655e65220cdc05cce5d.tar.gz |
This fixes the C++ xap_helper compilation on OpenBSD. Assignable `FILE *' pointers appear to only be supported on FreeBSD and glibc. Based on my reading of musl and NetBSD source code, this should also fix builds on those platforms.
Diffstat (limited to 'lib/PublicInbox/xap_helper.h')
-rw-r--r-- | lib/PublicInbox/xap_helper.h | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/lib/PublicInbox/xap_helper.h b/lib/PublicInbox/xap_helper.h index e10527d1..92210511 100644 --- a/lib/PublicInbox/xap_helper.h +++ b/lib/PublicInbox/xap_helper.h @@ -50,9 +50,18 @@ # define SET_MAX_EXPANSION set_max_wildcard_expansion #endif +#if defined(__FreeBSD__) || defined(__GLIBC__) +# define STDERR_ASSIGNABLE (1) +#else +# define STDERR_ASSIGNABLE (0) +#endif + static const int sock_fd = 0; // SOCK_SEQPACKET as stdin :P static pid_t parent_pid; +#if STDERR_ASSIGNABLE static FILE *orig_err = stderr; +#endif +static int orig_err_fd = -1; static void *srch_tree; // tsearch + tdelete + twalk static pid_t *worker_pids; // nr => pid static unsigned long nworker; @@ -820,6 +829,37 @@ static void cleanup_pids(void) worker_pids = NULL; } +static void stderr_set(FILE *tmp_err) +{ +#if STDERR_ASSIGNABLE + if (my_setlinebuf(tmp_err)) + perror("W: setlinebuf(tmp_err)"); + stderr = tmp_err; + return; +#endif + int fd = fileno(tmp_err); + if (fd < 0) err(EXIT_FAILURE, "BUG: fileno(tmp_err)"); + while (dup2(fd, STDERR_FILENO) < 0) { + if (errno != EINTR) + err(EXIT_FAILURE, "dup2(%d => 2)", fd); + } +} + +static void stderr_restore(FILE *tmp_err) +{ +#if STDERR_ASSIGNABLE + stderr = orig_err; + return; +#endif + if (ferror(stderr) | fflush(stderr)) + perror("ferror|fflush stderr"); + while (dup2(orig_err_fd, STDERR_FILENO) < 0) { + if (errno != EINTR) + err(EXIT_FAILURE, "dup2(%d => 2)", orig_err_fd); + } + clearerr(stderr); +} + static void recv_loop(void) // worker process loop { static char rbuf[4096 * 33]; // per-process @@ -828,18 +868,15 @@ static void recv_loop(void) // worker process loop struct req req = {}; if (!recv_req(&req, rbuf, &len)) continue; - if (req.fp[1]) { - if (my_setlinebuf(req.fp[1])) - perror("W: setlinebuf(req.fp[1])"); - stderr = req.fp[1]; - } + if (req.fp[1]) + stderr_set(req.fp[1]); req.argc = (int)SPLIT2ARGV(req.argv, rbuf, len); if (req.argc > 0) dispatch(&req); if (ferror(req.fp[0]) | fclose(req.fp[0])) perror("ferror|fclose fp[0]"); if (req.fp[1]) { - stderr = orig_err; + stderr_restore(req.fp[1]); if (ferror(req.fp[1]) | fclose(req.fp[1])) perror("ferror|fclose fp[1]"); } @@ -895,6 +932,12 @@ int main(int argc, char *argv[]) code_nrp_init(); atexit(cleanup_all); + if (!STDERR_ASSIGNABLE) { + orig_err_fd = dup(STDERR_FILENO); + if (orig_err_fd < 0) + err(EXIT_FAILURE, "dup(2)"); + } + nworker = 0; #ifdef _SC_NPROCESSORS_ONLN long j = sysconf(_SC_NPROCESSORS_ONLN); |