From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 475D31F51B for ; Wed, 30 Aug 2023 05:10:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1693372246; bh=usr1HG91VxfzTf7WSy7aC9XfYJlI0XlxqC536OD9HVE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=RIVTM4gc9F63U+qE3TNeARpbaOQPRs6jle3wiMg3sseSj7U156F6SuQmXJK0my54z pgA+sFxAiaYkd4BGbAGPnxPaWxQVf9TCeP4fpAtUwzGgaCVR0xU7t/F1Cygqj/5sZm R5JZ99gQvyjEZ81Je3nTUUevb1+mv9d9quTHb2s4= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 6/7] xap_helper.h: limit stderr assignment to glibc+FreeBSD Date: Wed, 30 Aug 2023 05:10:44 +0000 Message-Id: <20230830051045.330641-7-e@80x24.org> In-Reply-To: <20230830051045.330641-1-e@80x24.org> References: <20230830051045.330641-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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. --- lib/PublicInbox/xap_helper.h | 55 ++++++++++++++++++++++++++++++++---- 1 file 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);