diff --git a/man/launcher.1.md b/man/launcher.1.md index d2afb561a2d7107a4bc04d12a39868f2857de1df..4f0c512767d57398724ebbaf125c7b4d920a8235 100644 --- a/man/launcher.1.md +++ b/man/launcher.1.md @@ -12,6 +12,7 @@ pressure-vessel-launcher - server to launch processes in a container **pressure-vessel-launcher** [**--replace**] [**--verbose**] +[**--info-fd**] *N* {**--bus-name** *NAME*|**--socket** *SOCKET*|**--socket-directory** *PATH*} # DESCRIPTION @@ -52,6 +53,11 @@ D-Bus session bus, and executes arbitrary commands as subprocesses. readable, meaning either data is available or end-of-file has been reached. +**--info-fd** *FD* +: Print details of the server on *FD* (see **OUTPUT** below). + This fd will be closed (reach end-of-file) when the server is ready. + The default is standard output, equivalent to **--info-fd=1**. + **--replace** : When used with **--bus-name**, allow other **pressure-vessel-launcher** processes to take over the bus name, @@ -64,7 +70,9 @@ D-Bus session bus, and executes arbitrary commands as subprocesses. # OUTPUT **pressure-vessel-launcher** prints zero or more lines of -structured text on standard output, and then closes standard output: +structured text on the file descriptor specified by **--info-fd**, +and then closes both the **--info-fd** and standard output. The default +**--info-fd** is standard output. **socket=**PATH : The launcher is listening on *PATH*, and can be contacted by @@ -86,11 +94,12 @@ structured text on standard output, and then closes standard output: (such as **dbus-send --session**) to the session bus and sending method calls to _NAME_. -Clients must wait until after standard output has been closed, or wait -for the bus name to appear, before connecting by bus name. +Clients must wait until after either the **--info-fd** or standard output +has been closed, or wait for the bus name to appear, before connecting +by bus name. -Clients must wait until after standard output has been closed before -connecting by socket name. +Clients must wait until after either the **--info-fd** or standard output +has been closed before connecting by socket name. Unstructured diagnostic messages are printed on standard error, which remains open throughout. @@ -211,13 +220,15 @@ instead of fifos. mkfifo "${tmpdir}/ready-fifo" pressure-vessel-wrap \ --filesystem="${tmpdir}" \ + --pass-fd=3 ... \ -- \ pressure-vessel-launcher \ --exit-on-readable=0 \ + --info-fd=3 \ --socket="${tmpdir}/launcher" \ < "${tmpdir}/exit-fifo" \ - > "${tmpdir}/ready-fifo" \ + 3> "${tmpdir}/ready-fifo" \ & launcher_pid="$!" sleep infinity > "${tmpdir}/exit-fifo" & diff --git a/src/launcher.c b/src/launcher.c index e26df69e5db7426c06e5768b1da511881e644cac..6e76b72d892fb95b95f7eb8b6296a762f987da6b 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -57,12 +57,27 @@ typedef GDBusServer AutoDBusServer; G_DEFINE_AUTOPTR_CLEANUP_FUNC(AutoDBusServer, g_object_unref) static FILE *original_stdout = NULL; +static FILE *info_fh = NULL; static GDBusConnection *session_bus = NULL; static GHashTable *client_pid_data_hash = NULL; static guint name_owner_id = 0; static GMainLoop *main_loop; static PvLauncher1 *launcher; +/* + * Close the --info-fd, and also close standard output (if different). + */ +static void +close_info_fh (void) +{ + if (info_fh == original_stdout) + original_stdout = NULL; + else + g_clear_pointer (&original_stdout, fclose); + + g_clear_pointer (&info_fh, fclose); +} + static void skeleton_died_cb (gpointer data) { @@ -558,10 +573,10 @@ on_name_acquired (GDBusConnection *connection, if (*ret == EX_UNAVAILABLE) { *ret = 0; - g_assert (original_stdout != NULL); - fprintf (original_stdout, "bus_name=%s\n", name); - fflush (original_stdout); - g_clear_pointer (&original_stdout, fclose); + g_assert (info_fh != NULL); + fprintf (info_fh, "bus_name=%s\n", name); + fflush (info_fh); + close_info_fh (); } } @@ -963,6 +978,7 @@ set_up_exit_on_readable (int fd, static gchar *opt_bus_name = NULL; static gint opt_exit_on_readable_fd = -1; +static gint opt_info_fd = -1; static gboolean opt_replace = FALSE; static gchar *opt_socket = NULL; static gchar *opt_socket_directory = NULL; @@ -980,6 +996,11 @@ static GOptionEntry options[] = "Exit when data is available for reading or when end-of-file is " "reached on this fd, usually 0 for stdin.", "FD" }, + { "info-fd", '\0', + G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &opt_info_fd, + "Indicate readiness and print details of how to connect on this " + "file descriptor instead of stdout.", + "FD" }, { "replace", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_replace, "Replace a previous instance with the same bus name. " @@ -1076,6 +1097,24 @@ main (int argc, goto out; } + if (opt_info_fd > 0) /* < 0 means unset, and 0 is stdout itself */ + { + info_fh = fdopen (opt_info_fd, "w"); + + if (info_fh == NULL) + { + glnx_null_throw_errno_prefix (error, + "Unable to create a stdio wrapper for fd %d", + opt_info_fd); + ret = EX_OSERR; + goto out; + } + } + else + { + info_fh = original_stdout; + } + if (opt_exit_on_readable_fd >= 0) { if (!set_up_exit_on_readable (opt_exit_on_readable_fd, @@ -1261,16 +1300,16 @@ main (int argc, } if (opt_socket != NULL) - fprintf (original_stdout, "socket=%s\n", opt_socket); + fprintf (info_fh, "socket=%s\n", opt_socket); if (server != NULL) - fprintf (original_stdout, "dbus_address=%s\n", + fprintf (info_fh, "dbus_address=%s\n", g_dbus_server_get_client_address (server)); if (opt_bus_name == NULL) { - fflush (original_stdout); - g_clear_pointer (&original_stdout, fclose); + fflush (info_fh); + close_info_fh (); } g_debug ("Entering main loop"); @@ -1307,7 +1346,7 @@ out: ret = EX_UNAVAILABLE; g_clear_error (&local_error); - g_clear_pointer (&original_stdout, fclose); + close_info_fh (); g_debug ("Exiting with status %d", ret); return ret;