diff mbox series

[7/7] t/helper/simple-ipc: convert test-simple-ipc to use start_bg_command

Message ID 57f29feaadb4a732892cd193b2a1d3c838f09421.1631738177.git.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series Builtin FSMonitor Part 1 | expand

Commit Message

Jeff Hostetler Sept. 15, 2021, 8:36 p.m. UTC
From: Jeff Hostetler <jeffhost@microsoft.com>

Convert test helper to use `start_bg_command()` when spawning a server
daemon in the background rather than blocks of platform-specific code.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
---
 t/helper/test-simple-ipc.c | 193 ++++++++-----------------------------
 1 file changed, 40 insertions(+), 153 deletions(-)

Comments

Taylor Blau Sept. 16, 2021, 5:06 a.m. UTC | #1
On Wed, Sep 15, 2021 at 08:36:17PM +0000, Jeff Hostetler via GitGitGadget wrote:
> From: Jeff Hostetler <jeffhost@microsoft.com>
>
> Convert test helper to use `start_bg_command()` when spawning a server
> daemon in the background rather than blocks of platform-specific code.
>
> Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
> ---
>  t/helper/test-simple-ipc.c | 193 ++++++++-----------------------------
>  1 file changed, 40 insertions(+), 153 deletions(-)
>
> diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
> index 91345180750..59a950f3b00 100644
> --- a/t/helper/test-simple-ipc.c
> +++ b/t/helper/test-simple-ipc.c
> @@ -9,6 +9,7 @@
>  #include "parse-options.h"
>  #include "thread-utils.h"
>  #include "strvec.h"
> +#include "run-command.h"
>
>  #ifndef SUPPORTS_SIMPLE_IPC
>  int cmd__simple_ipc(int argc, const char **argv)
> @@ -274,178 +275,64 @@ static int daemon__run_server(void)
>  	return ret;
>  }
>
> -#ifndef GIT_WINDOWS_NATIVE
> -/*
> - * This is adapted from `daemonize()`.  Use `fork()` to directly create and
> - * run the daemon in a child process.
> - */
> -static int spawn_server(pid_t *pid)
> -{
> -	struct ipc_server_opts opts = {
> -		.nr_threads = cl_args.nr_threads,
> -	};
> +static start_bg_wait_cb bg_wait_cb;

This whole patch is delightful to read, as the new implementation is so
much cleaner as a result of the earlier work in this series.

Am I correct in assuming that this is to encourage a compiler error if
bg_wait_cb does not satisfy the type of start_bg_wait_cb? If so, then I
think we are already getting that by trying to pass bg_wait_cb to
start_bg_command().

E.g., applying this (intentionally broken) diff on top:

--- 8< ---

diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
index 59a950f3b0..3aed787206 100644
--- a/t/helper/test-simple-ipc.c
+++ b/t/helper/test-simple-ipc.c
@@ -275,9 +275,7 @@ static int daemon__run_server(void)
 	return ret;
 }

-static start_bg_wait_cb bg_wait_cb;
-
-static int bg_wait_cb(void *cb_data, const struct child_process *cp)
+static int bg_wait_cb(const void *cb_data, const struct child_process *cp)
 {
 	int s = ipc_get_active_state(cl_args.path);

--- >8 ---

and then compiling still warns of a mismatched type when calling
start_bg_command().

> -	*pid = fork();
> -
> -	switch (*pid) {
> -	case 0:
> -		if (setsid() == -1)
> -			error_errno(_("setsid failed"));
> -		close(0);
> -		close(1);
> -		close(2);
> -		sanitize_stdfds();
> +static int bg_wait_cb(void *cb_data, const struct child_process *cp)
> +{
> +	int s = ipc_get_active_state(cl_args.path);
>
> -		return ipc_server_run(cl_args.path, &opts, test_app_cb,
> -				      (void*)&my_app_data);
> +	switch (s) {
> +	case IPC_STATE__LISTENING:
> +		/* child is "ready" */
> +		return 0;
>
> -	case -1:
> -		return error_errno(_("could not spawn daemon in the background"));
> +	case IPC_STATE__NOT_LISTENING:
> +	case IPC_STATE__PATH_NOT_FOUND:
> +		/* give child more time */
> +		return 1;
>
>  	default:

I'm always a little hesitant to have default cases when switch over enum
types, since it suppresses the warning when there's a new value of that
type. But we already have a similar default in client__probe_server().

> -		else if (pid_seen == pid_child) {
> -			/*
> -			 * The new child daemon process shutdown while
> -			 * it was starting up, so it is not listening
> -			 * on the socket.
> -			 *
> -			 * Try to ping the socket in the odd chance
> -			 * that another daemon started (or was already
> -			 * running) while our child was starting.
> -			 *
> -			 * Again, we don't care who services the socket.
> -			 */
> -			s = ipc_get_active_state(cl_args.path);
> -			if (s == IPC_STATE__LISTENING)
> -				return 0;
> +	default:

Ditto.

Thanks,
Taylor
Ævar Arnfjörð Bjarmason Sept. 16, 2021, 5:55 a.m. UTC | #2
On Wed, Sep 15 2021, Jeff Hostetler via GitGitGadget wrote:

[...]

> +	default:
> +	case SBGR_ERROR:
> +	case SBGR_CB_ERROR:
> +		return error("daemon failed to start");
>  
> -			/*
> -			 * We don't care about the WEXITSTATUS() nor
> -			 * any of the WIF*(status) values because
> -			 * `cmd__simple_ipc()` does the `!!result`
> -			 * trick on all function return values.
> -			 *
> -			 * So it is sufficient to just report the
> -			 * early shutdown as an error.
> -			 */
> -			return error(_("daemon failed to start"));
> -		}
> +	case SBGR_TIMEOUT:
> +		return error("daemon not online yet");
>  
> -		else
> -			return error(_("waitpid is confused"));
> +	case SBGR_DIED:
> +		return error("daemon terminated");
>  	}
>  }

It's not mentioned in the commit message, but the while-we're-at-it
dropping of _() makes sense here, it shouldn't have been used in a test
helper to begin with. I.e. translators don't need to be translating
stuff purely internal to the test suite.
Jeff Hostetler Sept. 17, 2021, 7:41 p.m. UTC | #3
On 9/16/21 1:06 AM, Taylor Blau wrote:
> On Wed, Sep 15, 2021 at 08:36:17PM +0000, Jeff Hostetler via GitGitGadget wrote:
>> From: Jeff Hostetler <jeffhost@microsoft.com>
>>
>> Convert test helper to use `start_bg_command()` when spawning a server
>> daemon in the background rather than blocks of platform-specific code.
>>
>> Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
>> ---
>>   t/helper/test-simple-ipc.c | 193 ++++++++-----------------------------
>>   1 file changed, 40 insertions(+), 153 deletions(-)
>>
>> diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
>> index 91345180750..59a950f3b00 100644
>> --- a/t/helper/test-simple-ipc.c
>> +++ b/t/helper/test-simple-ipc.c
>> @@ -9,6 +9,7 @@
>>   #include "parse-options.h"
>>   #include "thread-utils.h"
>>   #include "strvec.h"
>> +#include "run-command.h"
>>
>>   #ifndef SUPPORTS_SIMPLE_IPC
>>   int cmd__simple_ipc(int argc, const char **argv)
>> @@ -274,178 +275,64 @@ static int daemon__run_server(void)
>>   	return ret;
>>   }
>>
>> -#ifndef GIT_WINDOWS_NATIVE
>> -/*
>> - * This is adapted from `daemonize()`.  Use `fork()` to directly create and
>> - * run the daemon in a child process.
>> - */
>> -static int spawn_server(pid_t *pid)
>> -{
>> -	struct ipc_server_opts opts = {
>> -		.nr_threads = cl_args.nr_threads,
>> -	};
>> +static start_bg_wait_cb bg_wait_cb;
> 
> This whole patch is delightful to read, as the new implementation is so
> much cleaner as a result of the earlier work in this series.
> 
> Am I correct in assuming that this is to encourage a compiler error if
> bg_wait_cb does not satisfy the type of start_bg_wait_cb? If so, then I
> think we are already getting that by trying to pass bg_wait_cb to
> start_bg_command().

I use that trick to get the compiler to give me a compiler error at the
point of the function declaration.

For example, If I add an arg to the function that doesn't match what's
in the prototype definition, I get:

t/helper/test-simple-ipc.c:280:12: error: conflicting types for 'bg_wait_cb'
static int bg_wait_cb(const struct child_process *cp, void *cb_data, int 
foo)
            ^
t/helper/test-simple-ipc.c:278:25: note: previous declaration is here
static start_bg_wait_cb bg_wait_cb;
                         ^
1 error generated.

Yes, we may get an error when the function pointer is referenced in
start_bg_command() or if we're using it to initialize a vtable or
something, but those errors are further away from the actual error
(and sometimes they can be a little cryptic).

Also, it helps document that this function's signature is predefined
for a reason.

It's a quirky trick I know, but it has served me well over the years.
	
> 
> E.g., applying this (intentionally broken) diff on top:
> 
> --- 8< ---
> 
> diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
> index 59a950f3b0..3aed787206 100644
> --- a/t/helper/test-simple-ipc.c
> +++ b/t/helper/test-simple-ipc.c
> @@ -275,9 +275,7 @@ static int daemon__run_server(void)
>   	return ret;
>   }
> 
> -static start_bg_wait_cb bg_wait_cb;
> -
> -static int bg_wait_cb(void *cb_data, const struct child_process *cp)
> +static int bg_wait_cb(const void *cb_data, const struct child_process *cp)
>   {
>   	int s = ipc_get_active_state(cl_args.path);
> 
> --- >8 ---
> 
> and then compiling still warns of a mismatched type when calling
> start_bg_command().
> 
>> -	*pid = fork();
>> -
>> -	switch (*pid) {
>> -	case 0:
>> -		if (setsid() == -1)
>> -			error_errno(_("setsid failed"));
>> -		close(0);
>> -		close(1);
>> -		close(2);
>> -		sanitize_stdfds();
>> +static int bg_wait_cb(void *cb_data, const struct child_process *cp)
>> +{
>> +	int s = ipc_get_active_state(cl_args.path);
>>
>> -		return ipc_server_run(cl_args.path, &opts, test_app_cb,
>> -				      (void*)&my_app_data);
>> +	switch (s) {
>> +	case IPC_STATE__LISTENING:
>> +		/* child is "ready" */
>> +		return 0;
>>
>> -	case -1:
>> -		return error_errno(_("could not spawn daemon in the background"));
>> +	case IPC_STATE__NOT_LISTENING:
>> +	case IPC_STATE__PATH_NOT_FOUND:
>> +		/* give child more time */
>> +		return 1;
>>
>>   	default:
> 
> I'm always a little hesitant to have default cases when switch over enum
> types, since it suppresses the warning when there's a new value of that
> type. But we already have a similar default in client__probe_server().

Do all compilers now handle switching over an enum and detect unhandled
cases?  Once upon a time that wasn't the case IIRC.

>...
> 
> Ditto.
> 
> Thanks,
> Taylor
>
Ævar Arnfjörð Bjarmason Sept. 18, 2021, 8:59 a.m. UTC | #4
On Fri, Sep 17 2021, Jeff Hostetler wrote:

> On 9/16/21 1:06 AM, Taylor Blau wrote:
>> On Wed, Sep 15, 2021 at 08:36:17PM +0000, Jeff Hostetler via GitGitGadget wrote:
>>> From: Jeff Hostetler <jeffhost@microsoft.com>
>>>
>>> Convert test helper to use `start_bg_command()` when spawning a server
>>> daemon in the background rather than blocks of platform-specific code.
>>>
>>> Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
>>> ---
>>>   t/helper/test-simple-ipc.c | 193 ++++++++-----------------------------
>>>   1 file changed, 40 insertions(+), 153 deletions(-)
>>>
>>> diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
>>> index 91345180750..59a950f3b00 100644
>>> --- a/t/helper/test-simple-ipc.c
>>> +++ b/t/helper/test-simple-ipc.c
>>> @@ -9,6 +9,7 @@
>>>   #include "parse-options.h"
>>>   #include "thread-utils.h"
>>>   #include "strvec.h"
>>> +#include "run-command.h"
>>>
>>>   #ifndef SUPPORTS_SIMPLE_IPC
>>>   int cmd__simple_ipc(int argc, const char **argv)
>>> @@ -274,178 +275,64 @@ static int daemon__run_server(void)
>>>   	return ret;
>>>   }
>>>
>>> -#ifndef GIT_WINDOWS_NATIVE
>>> -/*
>>> - * This is adapted from `daemonize()`.  Use `fork()` to directly create and
>>> - * run the daemon in a child process.
>>> - */
>>> -static int spawn_server(pid_t *pid)
>>> -{
>>> -	struct ipc_server_opts opts = {
>>> -		.nr_threads = cl_args.nr_threads,
>>> -	};
>>> +static start_bg_wait_cb bg_wait_cb;
>> This whole patch is delightful to read, as the new implementation is
>> so
>> much cleaner as a result of the earlier work in this series.
>> Am I correct in assuming that this is to encourage a compiler error
>> if
>> bg_wait_cb does not satisfy the type of start_bg_wait_cb? If so, then I
>> think we are already getting that by trying to pass bg_wait_cb to
>> start_bg_command().
>
> I use that trick to get the compiler to give me a compiler error at the
> point of the function declaration.
>
> For example, If I add an arg to the function that doesn't match what's
> in the prototype definition, I get:
>
> t/helper/test-simple-ipc.c:280:12: error: conflicting types for 'bg_wait_cb'
> static int bg_wait_cb(const struct child_process *cp, void *cb_data,
> int foo)
>            ^
> t/helper/test-simple-ipc.c:278:25: note: previous declaration is here
> static start_bg_wait_cb bg_wait_cb;
>                         ^
> 1 error generated.
>
> Yes, we may get an error when the function pointer is referenced in
> start_bg_command() or if we're using it to initialize a vtable or
> something, but those errors are further away from the actual error
> (and sometimes they can be a little cryptic).
>
> Also, it helps document that this function's signature is predefined
> for a reason.
>
> It's a quirky trick I know, but it has served me well over the years.

I haven't seen this idiom before. I think it's best to avoid patterns
designed to massage messages out of any specific compilers/versions.

It seems inevitable that it'll either be counter-productive or
redundant. Here with clang v11 doing this makes the warning
worse. I.e. without the forward declaration:

    t/helper/test-simple-ipc.c:315:31: error: incompatible function
    pointer types passing 'int (void *, const struct child_process *,
    int)' to parameter of type ' start_bg_wait_cb *' (aka 'int (*)(void
    *, const struct child_process *)')
    [-Werror,-Wincompatible-function-pointer-types]
            sbgr = start_bg_command(&cp, bg_wait_cb, NULL, cl_args.max_wait_sec);
                                         ^~~~~~~~~~
    ./run-command.h:564:29: note: passing argument to parameter 'wait_cb' here
                                      start_bg_wait_cb *wait_cb,
                                                        ^
    1 error generated.

I.e. we get the specific warning category for this type of error
(-Werror,-Wincompatible-function-pointer-types), and we're pointed at
the caller in question (which to be fair, it seems you don't prefer),
but also a reference to the run-command.h definition.

Most importantly, we get quoted what the type is/should be, which is
missing with the forward declaration. It's the equivalent of saying "you
did bad!" instead of "you did bad X, do Y instead!".

>> E.g., applying this (intentionally broken) diff on top:
>> --- 8< ---
>> diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
>> index 59a950f3b0..3aed787206 100644
>> --- a/t/helper/test-simple-ipc.c
>> +++ b/t/helper/test-simple-ipc.c
>> @@ -275,9 +275,7 @@ static int daemon__run_server(void)
>>   	return ret;
>>   }
>> -static start_bg_wait_cb bg_wait_cb;
>> -
>> -static int bg_wait_cb(void *cb_data, const struct child_process *cp)
>> +static int bg_wait_cb(const void *cb_data, const struct child_process *cp)
>>   {
>>   	int s = ipc_get_active_state(cl_args.path);
>> --- >8 ---
>> and then compiling still warns of a mismatched type when calling
>> start_bg_command().
>> 
>>> -	*pid = fork();
>>> -
>>> -	switch (*pid) {
>>> -	case 0:
>>> -		if (setsid() == -1)
>>> -			error_errno(_("setsid failed"));
>>> -		close(0);
>>> -		close(1);
>>> -		close(2);
>>> -		sanitize_stdfds();
>>> +static int bg_wait_cb(void *cb_data, const struct child_process *cp)
>>> +{
>>> +	int s = ipc_get_active_state(cl_args.path);
>>>
>>> -		return ipc_server_run(cl_args.path, &opts, test_app_cb,
>>> -				      (void*)&my_app_data);
>>> +	switch (s) {
>>> +	case IPC_STATE__LISTENING:
>>> +		/* child is "ready" */
>>> +		return 0;
>>>
>>> -	case -1:
>>> -		return error_errno(_("could not spawn daemon in the background"));
>>> +	case IPC_STATE__NOT_LISTENING:
>>> +	case IPC_STATE__PATH_NOT_FOUND:
>>> +		/* give child more time */
>>> +		return 1;
>>>
>>>   	default:
>> I'm always a little hesitant to have default cases when switch over
>> enum
>> types, since it suppresses the warning when there's a new value of that
>> type. But we already have a similar default in client__probe_server().
>
> Do all compilers now handle switching over an enum and detect unhandled
> cases?  Once upon a time that wasn't the case IIRC.

I don't think so, but the ones we widely use do, i.e. clang and gcc at
least.

For this sort of thing it really doesn't matter if *all* compilers
support it, since we'll only need to catch such "missing enum arm"
issues with one of them.

E.g. in my 338abb0f045 (builtins + test helpers: use return instead of
exit() in cmd_*, 2021-06-08) I fixed something that I've only gotten
Oracle SunCC to emit (gcc and clang don't detect it), but as long as
that one compiler does & someone checks it regularly...

By having a "default" case you're hiding that detection from the
compilers capable of detecting a logic error in this code, whereas if
the compiler can't do that it'll just ignore it.
diff mbox series

Patch

diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c
index 91345180750..59a950f3b00 100644
--- a/t/helper/test-simple-ipc.c
+++ b/t/helper/test-simple-ipc.c
@@ -9,6 +9,7 @@ 
 #include "parse-options.h"
 #include "thread-utils.h"
 #include "strvec.h"
+#include "run-command.h"
 
 #ifndef SUPPORTS_SIMPLE_IPC
 int cmd__simple_ipc(int argc, const char **argv)
@@ -274,178 +275,64 @@  static int daemon__run_server(void)
 	return ret;
 }
 
-#ifndef GIT_WINDOWS_NATIVE
-/*
- * This is adapted from `daemonize()`.  Use `fork()` to directly create and
- * run the daemon in a child process.
- */
-static int spawn_server(pid_t *pid)
-{
-	struct ipc_server_opts opts = {
-		.nr_threads = cl_args.nr_threads,
-	};
+static start_bg_wait_cb bg_wait_cb;
 
-	*pid = fork();
-
-	switch (*pid) {
-	case 0:
-		if (setsid() == -1)
-			error_errno(_("setsid failed"));
-		close(0);
-		close(1);
-		close(2);
-		sanitize_stdfds();
+static int bg_wait_cb(void *cb_data, const struct child_process *cp)
+{
+	int s = ipc_get_active_state(cl_args.path);
 
-		return ipc_server_run(cl_args.path, &opts, test_app_cb,
-				      (void*)&my_app_data);
+	switch (s) {
+	case IPC_STATE__LISTENING:
+		/* child is "ready" */
+		return 0;
 
-	case -1:
-		return error_errno(_("could not spawn daemon in the background"));
+	case IPC_STATE__NOT_LISTENING:
+	case IPC_STATE__PATH_NOT_FOUND:
+		/* give child more time */
+		return 1;
 
 	default:
-		return 0;
+	case IPC_STATE__INVALID_PATH:
+	case IPC_STATE__OTHER_ERROR:
+		/* all the time in world won't help */
+		return -1;
 	}
 }
-#else
-/*
- * Conceptually like `daemonize()` but different because Windows does not
- * have `fork(2)`.  Spawn a normal Windows child process but without the
- * limitations of `start_command()` and `finish_command()`.
- */
-static int spawn_server(pid_t *pid)
-{
-	char test_tool_exe[MAX_PATH];
-	struct strvec args = STRVEC_INIT;
-	int in, out;
-
-	GetModuleFileNameA(NULL, test_tool_exe, MAX_PATH);
-
-	in = open("/dev/null", O_RDONLY);
-	out = open("/dev/null", O_WRONLY);
-
-	strvec_push(&args, test_tool_exe);
-	strvec_push(&args, "simple-ipc");
-	strvec_push(&args, "run-daemon");
-	strvec_pushf(&args, "--name=%s", cl_args.path);
-	strvec_pushf(&args, "--threads=%d", cl_args.nr_threads);
-
-	*pid = mingw_spawnvpe(args.v[0], args.v, NULL, NULL, in, out, out);
-	close(in);
-	close(out);
-
-	strvec_clear(&args);
 
-	if (*pid < 0)
-		return error(_("could not spawn daemon in the background"));
-
-	return 0;
-}
-#endif
-
-/*
- * This is adapted from `wait_or_whine()`.  Watch the child process and
- * let it get started and begin listening for requests on the socket
- * before reporting our success.
- */
-static int wait_for_server_startup(pid_t pid_child)
+static int daemon__start_server(void)
 {
-	int status;
-	pid_t pid_seen;
-	enum ipc_active_state s;
-	time_t time_limit, now;
+	struct child_process cp = CHILD_PROCESS_INIT;
+	enum start_bg_result sbgr;
 
-	time(&time_limit);
-	time_limit += cl_args.max_wait_sec;
+	strvec_push(&cp.args, "test-tool");
+	strvec_push(&cp.args, "simple-ipc");
+	strvec_push(&cp.args, "run-daemon");
+	strvec_pushf(&cp.args, "--name=%s", cl_args.path);
+	strvec_pushf(&cp.args, "--threads=%d", cl_args.nr_threads);
 
-	for (;;) {
-		pid_seen = waitpid(pid_child, &status, WNOHANG);
+	cp.no_stdin = 1;
+	cp.no_stdout = 1;
+	cp.no_stderr = 1;
 
-		if (pid_seen == -1)
-			return error_errno(_("waitpid failed"));
+	sbgr = start_bg_command(&cp, bg_wait_cb, NULL, cl_args.max_wait_sec);
 
-		else if (pid_seen == 0) {
-			/*
-			 * The child is still running (this should be
-			 * the normal case).  Try to connect to it on
-			 * the socket and see if it is ready for
-			 * business.
-			 *
-			 * If there is another daemon already running,
-			 * our child will fail to start (possibly
-			 * after a timeout on the lock), but we don't
-			 * care (who responds) if the socket is live.
-			 */
-			s = ipc_get_active_state(cl_args.path);
-			if (s == IPC_STATE__LISTENING)
-				return 0;
-
-			time(&now);
-			if (now > time_limit)
-				return error(_("daemon not online yet"));
-
-			continue;
-		}
+	switch (sbgr) {
+	case SBGR_READY:
+		return 0;
 
-		else if (pid_seen == pid_child) {
-			/*
-			 * The new child daemon process shutdown while
-			 * it was starting up, so it is not listening
-			 * on the socket.
-			 *
-			 * Try to ping the socket in the odd chance
-			 * that another daemon started (or was already
-			 * running) while our child was starting.
-			 *
-			 * Again, we don't care who services the socket.
-			 */
-			s = ipc_get_active_state(cl_args.path);
-			if (s == IPC_STATE__LISTENING)
-				return 0;
+	default:
+	case SBGR_ERROR:
+	case SBGR_CB_ERROR:
+		return error("daemon failed to start");
 
-			/*
-			 * We don't care about the WEXITSTATUS() nor
-			 * any of the WIF*(status) values because
-			 * `cmd__simple_ipc()` does the `!!result`
-			 * trick on all function return values.
-			 *
-			 * So it is sufficient to just report the
-			 * early shutdown as an error.
-			 */
-			return error(_("daemon failed to start"));
-		}
+	case SBGR_TIMEOUT:
+		return error("daemon not online yet");
 
-		else
-			return error(_("waitpid is confused"));
+	case SBGR_DIED:
+		return error("daemon terminated");
 	}
 }
 
-/*
- * This process will start a simple-ipc server in a background process and
- * wait for it to become ready.  This is like `daemonize()` but gives us
- * more control and better error reporting (and makes it easier to write
- * unit tests).
- */
-static int daemon__start_server(void)
-{
-	pid_t pid_child;
-	int ret;
-
-	/*
-	 * Run the actual daemon in a background process.
-	 */
-	ret = spawn_server(&pid_child);
-	if (pid_child <= 0)
-		return ret;
-
-	/*
-	 * Let the parent wait for the child process to get started
-	 * and begin listening for requests on the socket.
-	 */
-	ret = wait_for_server_startup(pid_child);
-
-	return ret;
-}
-
 /*
  * This process will run a quick probe to see if a simple-ipc server
  * is active on this path.