From patchwork Tue Mar 1 18:43:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Hostetler X-Patchwork-Id: 12765054 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1513C433F5 for ; Tue, 1 Mar 2022 18:44:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237057AbiCASpH (ORCPT ); Tue, 1 Mar 2022 13:45:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56952 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237035AbiCASox (ORCPT ); Tue, 1 Mar 2022 13:44:53 -0500 Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D959C5D1B7 for ; Tue, 1 Mar 2022 10:43:45 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id i66so1821845wma.5 for ; Tue, 01 Mar 2022 10:43:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=s2EOuiBEqM7u7pum9IZt5+l8da9mgIKwm8vheBUni5E=; b=htTMEtGgmEV5L7TJwUqR63n9tXM/p/BSJ2O+wA2/dBkJW7wsug8xG8d7CDAfDYcTrT yvFtIE/CmDTmHpERGl2Dw7OY1HNCD8Q2JDy4xDEnqv6x+CCd+SFiplPPFIB7KBMuMVkX npeIy2fvgyDAP4Cj0y84cyEHSr2Ue3lMgCP0isvYHLvA5AORSlFGYsOhuTOKACK4/JLV AnBXbBLYxokJk4HDy391FeZipVmWg6bnGDc1Ch5Kli2fxWnctEOd12yDOamz3ccm1Y0w OxofkRA2YIs0l5BfDQxzV4AA2Y6Dk1u5hA1CEQMmGptNmqa47VjKyyhgKBzXUyPb0YzY JitQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=s2EOuiBEqM7u7pum9IZt5+l8da9mgIKwm8vheBUni5E=; b=76SrO7YePRC69eIrV48w3SRbHu11yPmH/txvJP6tJy2hyQ3h0vQaeGUMmIWu4vzcoj LWoxBv2uMpVctJjDNA6+gnmzJuIiorcUvQiX6x3ZMiWEN5p9bqbqNmJKkG2soo3At4FP EkJfPClyvDE8CIKbagYhHKcRz8OqPaKdmak5EeHAon4A2iGBOFxfd7NrsXeoFyLhQTwG dkRKm7vWmog53LCDZc5mg8acw2TxyEO50KLxn6U30OBRSCZmck4rXGXRguTwcroTQosx YQUYjPjhWrXiu+cXIhecbAEWQOezS+SxKSPvAeGnqz5+bQS+sheoC41PWxa89QTntRu1 ybaw== X-Gm-Message-State: AOAM530KlOaCNhT2ouyMNRjyvRDWjhlYN3MAh6PWOcD5SiikMHnjcO+f gKO+YOFjj/VBMO1rC8WFLcR9pYq7HxI= X-Google-Smtp-Source: ABdhPJwSWKkkx6AGEq8YWQ4kujujdhLaJJKW6f0Wew6gKwT696+o8Oi2PYm6teI7TSOqD3b5Z3WVUw== X-Received: by 2002:a05:600c:4202:b0:382:a5d7:9ce5 with SMTP id x2-20020a05600c420200b00382a5d79ce5mr2038077wmh.45.1646160224178; Tue, 01 Mar 2022 10:43:44 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b1-20020a5d4d81000000b001e6993398e2sm14125775wru.75.2022.03.01.10.43.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 10:43:43 -0800 (PST) Message-Id: <8de40b0fe8b097534630cfac28fc7c84dd304463.1646160212.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 18:43:13 +0000 Subject: [PATCH v6 11/30] fsmonitor--daemon: implement 'start' command Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Bagas Sanjaya , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Jeff Hostetler , Eric Sunshine , Johannes Schindelin , Tao Klerks , Jeff Hostetler , Jeff Hostetler Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Jeff Hostetler From: Jeff Hostetler Implement 'git fsmonitor--daemon start' command. This command starts an instance of 'git fsmonitor--daemon run' in the background using the new 'start_bg_command()' function. We avoid the fork-and-call technique on Unix systems in favor of a fork-and-exec technique. This gives us more uniform Trace2 child-* events. It also makes our usage more consistent with Windows usage. On Windows, teach 'git fsmonitor--daemon run' to optionally call 'FreeConsole()' to release handles to the inherited Win32 console (despite being passed invalid handles for stdin/out/err). Without this, command prompts and powershell terminal windows could hang in "exit" until the last background child process exited or released their Win32 console handle. (This was not seen with git-bash shells because they don't have a Win32 console attached to them.) Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- builtin/fsmonitor--daemon.c | 109 +++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 950614f82f6..2f721aae016 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -9,6 +9,7 @@ #include "khash.h" static const char * const builtin_fsmonitor__daemon_usage[] = { + N_("git fsmonitor--daemon start []"), N_("git fsmonitor--daemon run []"), N_("git fsmonitor--daemon stop"), N_("git fsmonitor--daemon status"), @@ -22,6 +23,9 @@ static const char * const builtin_fsmonitor__daemon_usage[] = { #define FSMONITOR__IPC_THREADS "fsmonitor.ipcthreads" static int fsmonitor__ipc_threads = 8; +#define FSMONITOR__START_TIMEOUT "fsmonitor.starttimeout" +static int fsmonitor__start_timeout_sec = 60; + #define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup" static int fsmonitor__announce_startup = 0; @@ -36,6 +40,15 @@ static int fsmonitor_config(const char *var, const char *value, void *cb) return 0; } + if (!strcmp(var, FSMONITOR__START_TIMEOUT)) { + int i = git_config_int(var, value); + if (i < 0) + return error(_("value of '%s' out of range: %d"), + FSMONITOR__START_TIMEOUT, i); + fsmonitor__start_timeout_sec = i; + return 0; + } + if (!strcmp(var, FSMONITOR__ANNOUNCE_STARTUP)) { int is_bool; int i = git_config_bool_or_int(var, value, &is_bool); @@ -250,7 +263,7 @@ done: return err; } -static int try_to_run_foreground_daemon(void) +static int try_to_run_foreground_daemon(int detach_console) { /* * Technically, we don't need to probe for an existing daemon @@ -270,17 +283,106 @@ static int try_to_run_foreground_daemon(void) fflush(stderr); } +#ifdef GIT_WINDOWS_NATIVE + if (detach_console) + FreeConsole(); +#endif + return !!fsmonitor_run_daemon(); } +static start_bg_wait_cb bg_wait_cb; + +static int bg_wait_cb(const struct child_process *cp, void *cb_data) +{ + enum ipc_active_state s = fsmonitor_ipc__get_state(); + + switch (s) { + case IPC_STATE__LISTENING: + /* child is "ready" */ + return 0; + + case IPC_STATE__NOT_LISTENING: + case IPC_STATE__PATH_NOT_FOUND: + /* give child more time */ + return 1; + + default: + case IPC_STATE__INVALID_PATH: + case IPC_STATE__OTHER_ERROR: + /* all the time in world won't help */ + return -1; + } +} + +static int try_to_start_background_daemon(void) +{ + struct child_process cp = CHILD_PROCESS_INIT; + enum start_bg_result sbgr; + + /* + * Before we try to create a background daemon process, see + * if a daemon process is already listening. This makes it + * easier for us to report an already-listening error to the + * console, since our spawn/daemon can only report the success + * of creating the background process (and not whether it + * immediately exited). + */ + if (fsmonitor_ipc__get_state() == IPC_STATE__LISTENING) + die("fsmonitor--daemon is already running '%s'", + the_repository->worktree); + + if (fsmonitor__announce_startup) { + fprintf(stderr, _("starting fsmonitor-daemon in '%s'\n"), + the_repository->worktree); + fflush(stderr); + } + + cp.git_cmd = 1; + + strvec_push(&cp.args, "fsmonitor--daemon"); + strvec_push(&cp.args, "run"); + strvec_push(&cp.args, "--detach"); + strvec_pushf(&cp.args, "--ipc-threads=%d", fsmonitor__ipc_threads); + + cp.no_stdin = 1; + cp.no_stdout = 1; + cp.no_stderr = 1; + + sbgr = start_bg_command(&cp, bg_wait_cb, NULL, + fsmonitor__start_timeout_sec); + + switch (sbgr) { + case SBGR_READY: + return 0; + + default: + case SBGR_ERROR: + case SBGR_CB_ERROR: + return error("daemon failed to start"); + + case SBGR_TIMEOUT: + return error("daemon not online yet"); + + case SBGR_DIED: + return error("daemon terminated"); + } +} + int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix) { const char *subcmd; + int detach_console = 0; struct option options[] = { + OPT_BOOL(0, "detach", &detach_console, N_("detach from console")), OPT_INTEGER(0, "ipc-threads", &fsmonitor__ipc_threads, N_("use ipc worker threads")), + OPT_INTEGER(0, "start-timeout", + &fsmonitor__start_timeout_sec, + N_("max seconds to wait for background daemon startup")), + OPT_END() }; @@ -296,8 +398,11 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix) die(_("invalid 'ipc-threads' value (%d)"), fsmonitor__ipc_threads); + if (!strcmp(subcmd, "start")) + return !!try_to_start_background_daemon(); + if (!strcmp(subcmd, "run")) - return !!try_to_run_foreground_daemon(); + return !!try_to_run_foreground_daemon(detach_console); if (!strcmp(subcmd, "stop")) return !!do_as_client__send_stop();