Description: fix fbguard to exit to the OS only after fbserver is ready
 Exiting right after forking causes a race condition making it possible that
 the service says it is startew, but the fbserver process isn't ready yet to
 serve requests, because it hasn't called listen() yet.
 .
 The patch makes fbserver send SIGUSR1 to the fbguard parent process, which
 waits for SIGUSR1 before it returns the control to the OS.
Bug-Debian: https://bugs.debian.org/859234
Forwarded: https://sourceforge.net/p/firebird/mailman/message/35769037/
Author: Damyan Ivanov <dmn@debian.org>

--- a/src/remote/inet.cpp
+++ b/src/remote/inet.cpp
@@ -1169,6 +1169,12 @@ static rem_port* listener_socket(rem_por
 
 	inet_ports->registerPort(port);
 
+	char *parent_pid;
+	if (parent_pid = getenv("FB_SIGNAL_PROCESS"))
+	{
+		kill(atoi(parent_pid), SIGUSR1);
+	}
+
 	if (flag & SRVR_multi_client)
 	{
 		// Prevent the generation of dummy keepalive packets on the connect port.
--- a/src/utilities/guard/guard.cpp
+++ b/src/utilities/guard/guard.cpp
@@ -168,11 +168,30 @@ int CLIB_ROUTINE main( int argc, char **
 		exit(-5);
 	}
 
+	sigset_t ss, save_sig_mask;
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGUSR1);
+	sigprocmask(SIG_BLOCK, &ss, &save_sig_mask);
+
 	// detach from controlling tty
 	if (daemon && fork()) {
+		int sig;
+
+		struct timespec ts = { .tv_sec=15, .tv_nsec= 0 };
+		do {
+			sig = sigtimedwait( &ss, NULL, &ts );
+		} while ( sig == EINTR );
+
+		if ( sig != SIGUSR1 ) {
+			fprintf( stderr, "Time out waiting for fbserver process start\n");
+			exit(-4);
+		}
+
 		exit(0);
 	}
 
+	sigprocmask(SIG_SETMASK, &save_sig_mask, NULL);
+
 	// Keep stdout and stderr opened and let server emit output
 	// or redirect stdout/stderr to /dev/null or file by user choice
 	// If we want to daemonize - close all fds and let child to reopen it.
@@ -181,6 +200,7 @@ int CLIB_ROUTINE main( int argc, char **
 	divorce_terminal(mask);
 
 	time_t timer = 0;
+	bool first_start = true;
 
 	do {
 		int ret_code;
@@ -199,6 +219,18 @@ int CLIB_ROUTINE main( int argc, char **
 		}
 		timer = time(0);
 
+		if (first_start)
+		{
+			char pid[10];
+			snprintf(pid, sizeof(pid), "%d", getppid());
+			setenv("FB_SIGNAL_PROCESS", pid, 1);
+			first_start = false;
+		}
+		else
+		{
+			unsetenv("FB_SIGNAL_PROCESS");
+		}
+
 		pid_t child_pid =
 			UTIL_start_process(SERVER_BINARY, server_args, prog_name);
 		if (child_pid == -1)
