diff --git a/pressure-vessel/bwrap.c b/pressure-vessel/bwrap.c
index 0f64a4b5af9a62a8cbe8c9c7738ddd9b22fd5c5d..d2e2798e891bf103f8ae2fbcd7beb7ace25979a2 100644
--- a/pressure-vessel/bwrap.c
+++ b/pressure-vessel/bwrap.c
@@ -22,6 +22,7 @@
 #include <gio/gio.h>
 
 #include "bwrap.h"
+#include "utils.h"
 
 #include "steam-runtime-tools/resolve-in-sysroot-internal.h"
 
@@ -42,65 +43,14 @@ pv_bwrap_run_sync (FlatpakBwrap *bwrap,
                    int *exit_status_out,
                    GError **error)
 {
-  gint exit_status;
-  g_autofree gchar *output = NULL;
-  g_autofree gchar *errors = NULL;
-  guint i;
-  g_autoptr(GString) command = g_string_new ("");
-
   g_return_val_if_fail (bwrap != NULL, FALSE);
   g_return_val_if_fail (bwrap->argv->len >= 2, FALSE);
   g_return_val_if_fail (pv_bwrap_was_finished (bwrap), FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  if (exit_status_out != NULL)
-    *exit_status_out = -1;
-
-  for (i = 0; i < bwrap->argv->len; i++)
-    {
-      g_autofree gchar *quoted = NULL;
-      char *unquoted = g_ptr_array_index (bwrap->argv, i);
-
-      if (unquoted == NULL)
-        break;
-
-      quoted = g_shell_quote (unquoted);
-      g_string_append_printf (command, " %s", quoted);
-    }
-
-  g_debug ("run:%s", command->str);
-
-  /* We use LEAVE_DESCRIPTORS_OPEN to work around a deadlock in older GLib,
-   * and to avoid wasting a lot of time closing fds if the rlimit for
-   * maximum open file descriptors is high. Because we're waiting for the
-   * subprocess to finish anyway, it doesn't really matter that any fds
-   * that are not close-on-execute will get leaked into the child. */
-  if (!g_spawn_sync (NULL,  /* cwd */
-                     (char **) bwrap->argv->pdata,
-                     bwrap->envp,
-                     (G_SPAWN_SEARCH_PATH |
-                      G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
-                     NULL,
-                     NULL,
-                     &output,
-                     &errors,
-                     &exit_status,
-                     error))
-    return FALSE;
-
-  g_print ("%s", output);
-  g_printerr ("%s", errors);
-
-  if (exit_status_out != NULL)
-    {
-      if (WIFEXITED (exit_status))
-        *exit_status_out = WEXITSTATUS (exit_status);
-    }
-
-  if (!g_spawn_check_exit_status (exit_status, error))
-    return FALSE;
-
-  return TRUE;
+  return pv_run_sync ((const char * const *) bwrap->argv->pdata,
+                      (const char * const *) bwrap->envp,
+                      exit_status_out, NULL, error);
 }
 
 /**
diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index e4e036c82f484a28ae8aa563fbc3435ecbe30640..7dba36b97257d83913239de704464a74c5145091 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -325,7 +325,7 @@ runtime_architecture_init (RuntimeArchitecture *self,
    * assume that this is the same as whether we can run them
    * on the host, if different. */
   argv[0] = self->capsule_capture_libs;
-  self->ld_so = pv_capture_output (argv, NULL, NULL);
+  pv_run_sync (argv, NULL, NULL, &self->ld_so, NULL);
 
   if (self->ld_so == NULL)
     {
@@ -3432,9 +3432,9 @@ pv_runtime_get_ld_so (PvRuntime *self,
                               NULL);
       flatpak_bwrap_finish (temp_bwrap);
 
-      *ld_so_in_runtime = pv_capture_output (
-          (const char * const *) temp_bwrap->argv->pdata,
-          (const char * const *) temp_bwrap->envp, NULL);
+      pv_run_sync ((const char * const *) temp_bwrap->argv->pdata,
+                   (const char * const *) temp_bwrap->envp, NULL,
+                   ld_so_in_runtime, NULL);
     }
 
   return TRUE;
diff --git a/pressure-vessel/utils.c b/pressure-vessel/utils.c
index af84f80484f2e2b5aa94bb2dda78a773d50ddf95..2b11ea3271608213a8e75c087f2d3bc42b39592e 100644
--- a/pressure-vessel/utils.c
+++ b/pressure-vessel/utils.c
@@ -168,22 +168,28 @@ pv_search_path_append (GString *search_path,
   g_string_append (search_path, item);
 }
 
-gchar *
-pv_capture_output (const char * const * argv,
-                   const char * const * envp,
-                   GError **error)
+gboolean
+pv_run_sync (const char * const * argv,
+             const char * const * envp,
+             int *exit_status_out,
+             char **output_out,
+             GError **error)
 {
   gsize len;
-  gint wait_status;
+  gint exit_status;
   g_autofree gchar *output = NULL;
   g_autofree gchar *errors = NULL;
-  gsize i;
+  guint i;
   g_autoptr(GString) command = g_string_new ("");
 
-  g_return_val_if_fail (argv != NULL, NULL);
-  g_return_val_if_fail (argv[0] != NULL, NULL);
+  g_return_val_if_fail (argv != NULL, FALSE);
+  g_return_val_if_fail (argv[0] != NULL, FALSE);
+  g_return_val_if_fail (output_out == NULL || *output_out == NULL, FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
+  if (exit_status_out != NULL)
+    *exit_status_out = -1;
+
   for (i = 0; argv[i] != NULL; i++)
     {
       g_autofree gchar *quoted = g_shell_quote (argv[i]);
@@ -206,14 +212,17 @@ pv_capture_output (const char * const * argv,
                      NULL, NULL,
                      &output,
                      &errors,
-                     &wait_status,
+                     &exit_status,
                      error))
-    return NULL;
+    return FALSE;
 
   g_printerr ("%s", errors);
 
-  if (!g_spawn_check_exit_status (wait_status, error))
-    return NULL;
+  if (exit_status_out != NULL)
+    {
+      if (WIFEXITED (exit_status))
+        *exit_status_out = WEXITSTATUS (exit_status);
+    }
 
   len = strlen (output);
 
@@ -223,7 +232,13 @@ pv_capture_output (const char * const * argv,
 
   g_debug ("-> %s", output);
 
-  return g_steal_pointer (&output);
+  if (!g_spawn_check_exit_status (exit_status, error))
+    return FALSE;
+
+  if (output_out != NULL)
+    *output_out = g_steal_pointer (&output);
+
+  return TRUE;
 }
 
 /*
diff --git a/pressure-vessel/utils.h b/pressure-vessel/utils.h
index 5920b7b6ee4a30b1e2163f1e753fa0cf14795e23..cf08ccf76757cce8c33f5279857332354fa1552f 100644
--- a/pressure-vessel/utils.h
+++ b/pressure-vessel/utils.h
@@ -48,9 +48,11 @@ void pv_get_current_dirs (gchar **cwd_p,
 void pv_search_path_append (GString *search_path,
                             const gchar *item);
 
-gchar *pv_capture_output (const char * const * argv,
-                          const char * const * envp,
-                          GError **error);
+gboolean pv_run_sync (const char * const * argv,
+                      const char * const * envp,
+                      int *exit_status_out,
+                      char **output_out,
+                      GError **error);
 
 gpointer pv_hash_table_get_arbitrary_key (GHashTable *table);
 
diff --git a/tests/pressure-vessel/utils.c b/tests/pressure-vessel/utils.c
index 9fa84bb99e0e26d7134acaf3b2d6b9e00c014c9c..202431ff899bd3dabf0c12bc397d158483c76986 100644
--- a/tests/pressure-vessel/utils.c
+++ b/tests/pressure-vessel/utils.c
@@ -86,8 +86,8 @@ test_arbitrary_key (Fixture *f,
 }
 
 static void
-test_capture_output (Fixture *f,
-                     gconstpointer context)
+test_run_sync (Fixture *f,
+               gconstpointer context)
 {
   const gchar * argv[] =
   {
@@ -96,20 +96,27 @@ test_capture_output (Fixture *f,
   g_autofree gchar *output = NULL;
   g_autoptr(GError) error = NULL;
   g_auto(GStrv) envp = g_get_environ ();
+  int exit_status = -1;
 
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, NULL, &output, &error);
   g_assert_cmpstr (output, ==, "hello");
   g_assert_no_error (error);
   g_clear_pointer (&output, g_free);
 
+  pv_run_sync (argv, NULL, &exit_status, NULL, &error);
+  g_assert_cmpint (exit_status, ==, 0);
+  g_assert_no_error (error);
+
   argv[1] = "hello\\nworld";    /* deliberately no trailing newline */
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, "hello\nworld");
   g_clear_pointer (&output, g_free);
 
   argv[0] = "/nonexistent/doesnotexist";
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, -1);
   g_assert_nonnull (error);
 
   if (error->domain == G_SPAWN_ERROR
@@ -134,7 +141,8 @@ test_capture_output (Fixture *f,
 
   argv[0] = "false";
   argv[1] = NULL;
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 1);
   g_assert_error (error, G_SPAWN_EXIT_ERROR, 1);
   g_assert_cmpstr (output, ==, NULL);
   g_clear_error (&error);
@@ -142,7 +150,8 @@ test_capture_output (Fixture *f,
   argv[0] = "sh";
   argv[1] = "-euc";
   argv[2] = "echo \"$PATH\"";
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, g_getenv ("PATH"));
   g_clear_pointer (&output, g_free);
@@ -151,7 +160,8 @@ test_capture_output (Fixture *f,
   argv[0] = "sh";
   argv[1] = "-euc";
   argv[2] = "echo \"${FOO-unset}\"";
-  output = pv_capture_output (argv, (const char * const *) envp, &error);
+  pv_run_sync (argv, (const char * const *) envp, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, "bar");
   g_clear_pointer (&output, g_free);
@@ -160,7 +170,8 @@ test_capture_output (Fixture *f,
   argv[0] = "sh";
   argv[1] = "-euc";
   argv[2] = "echo \"${FOO-unset}\"";
-  output = pv_capture_output (argv, (const char * const *) envp, &error);
+  pv_run_sync (argv, (const char * const *) envp, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, "unset");
   g_clear_pointer (&output, g_free);
@@ -371,8 +382,8 @@ main (int argc,
   g_test_init (&argc, &argv, NULL);
   g_test_add ("/arbitrary-key", Fixture, NULL,
               setup, test_arbitrary_key, teardown);
-  g_test_add ("/capture-output", Fixture, NULL,
-              setup, test_capture_output, teardown);
+  g_test_add ("/run-sync", Fixture, NULL,
+              setup, test_run_sync, teardown);
   g_test_add ("/delete-dangling-symlink", Fixture, NULL,
               setup, test_delete_dangling_symlink, teardown);
   g_test_add ("/envp-cmp", Fixture, NULL, setup, test_envp_cmp, teardown);