diff --git a/pressure-vessel/launch.1.md b/pressure-vessel/launch.1.md
index a5e07bdf82f0916e9d7bc870b1acece16311eb48..182eaa74dbbf5a1aedb3c05ebce1f08ea3153659 100644
--- a/pressure-vessel/launch.1.md
+++ b/pressure-vessel/launch.1.md
@@ -67,7 +67,7 @@ as a subprocess of **pressure-vessel-launcher**.
     owned by the **flatpak-portal** per-user service, and the
     *COMMAND* is launched in a Flatpak sub-sandbox, similar to
     **flatpak-spawn**(1) without the **--host** option.
-    Options that alter how the sub-sandbox is created, such as
+    Most options that alter how the sub-sandbox is created, such as
     **--sandbox-flag**, are not currently supported.
     As with **org.freedesktop.Flatpak**, the
     **--terminate** option is not allowed in this mode.
@@ -90,6 +90,15 @@ as a subprocess of **pressure-vessel-launcher**.
     (standard input, standard output and standard error) are always
     forwarded.
 
+**--share-pids**
+:   If used with **--bus-name=org.freedesktop.portal.Flatpak**, use the
+    same process ID namespace for the new subsandbox as for the calling
+    process. This requires Flatpak 1.10 or later, running on a host
+    operating system where **bwrap**(1) is not and does not need to be
+    setuid root.
+
+    When communicating with a different API, this option is ignored.
+
 **--terminate**
 :   Instead of running a *COMMAND*, terminate the Launcher server.
 
diff --git a/pressure-vessel/launch.c b/pressure-vessel/launch.c
index e3935d9f4c72da383c2069199c0c1181cefcde46..1913af2c0491db22ce58e7ef2aaae751bdbf5050 100644
--- a/pressure-vessel/launch.c
+++ b/pressure-vessel/launch.c
@@ -2,7 +2,7 @@
  * pressure-vessel-launch — send IPC requests to create child processes
  *
  * Copyright © 2018 Red Hat, Inc.
- * Copyright © 2020 Collabora Ltd.
+ * Copyright © 2020-2021 Collabora Ltd.
  *
  * SPDX-License-Identifier: LGPL-2.1-or-later
  *
@@ -53,6 +53,8 @@ typedef enum {
   FLATPAK_SPAWN_FLAGS_NO_NETWORK = 1 << 3,
   FLATPAK_SPAWN_FLAGS_WATCH_BUS = 1 << 4, /* Since 1.2 */
   FLATPAK_SPAWN_FLAGS_EXPOSE_PIDS = 1 << 5, /* Since 1.6, optional */
+  FLATPAK_SPAWN_FLAGS_NOTIFY_START = 1 << 6,
+  FLATPAK_SPAWN_FLAGS_SHARE_PIDS = 1 << 7,
 } FlatpakSpawnFlags;
 
 typedef enum {
@@ -74,6 +76,10 @@ typedef enum {
   FLATPAK_SPAWN_SUPPORT_FLAGS_EXPOSE_PIDS = 1 << 0,
 } FlatpakSpawnSupportFlags;
 
+/* The same flag is reused: this feature is available under the same
+ * circumstances */
+#define FLATPAK_SPAWN_SUPPORT_FLAGS_SHARE_PIDS FLATPAK_SPAWN_SUPPORT_FLAGS_EXPOSE_PIDS
+
 typedef struct
 {
   const char *service_iface;
@@ -171,7 +177,7 @@ process_exited_cb (G_GNUC_UNUSED GDBusConnection *connection,
            * code specified neither WUNTRACED nor WIFSIGNALED, then exactly one
            * of WIFEXITED() or WIFSIGNALED() will be true.
            */
-          g_warning ("exit status %d is neither WIFEXITED() nor WIFSIGNALED()",
+          g_warning ("wait status %d is neither WIFEXITED() nor WIFSIGNALED()",
                      wait_status);
           exit_code = LAUNCH_EX_CANNOT_REPORT;
         }
@@ -327,7 +333,7 @@ name_owner_changed (G_GNUC_UNUSED GDBusConnection *connection,
                     G_GNUC_UNUSED const gchar     *interface_name,
                     G_GNUC_UNUSED const gchar     *signal_name,
                     GVariant                      *parameters,
-                    gpointer                       user_data)
+                    G_GNUC_UNUSED gpointer         user_data)
 {
   GMainLoop *loop = user_data;
   const char *name, *from, *to;
@@ -367,6 +373,108 @@ connection_closed_cb (G_GNUC_UNUSED GDBusConnection *conn,
   g_main_loop_quit (loop);
 }
 
+static guint32
+get_portal_version (void)
+{
+  static guint32 version = 0;
+
+  g_return_val_if_fail (api != NULL, 0);
+  g_return_val_if_fail (api == &host_api || api == &subsandbox_api, 0);
+
+  if (version == 0)
+    {
+      g_autoptr(GError) error = NULL;
+      g_autoptr(GVariant) reply =
+        g_dbus_connection_call_sync (bus_or_peer_connection,
+                                     api->service_bus_name,
+                                     api->service_obj_path,
+                                     "org.freedesktop.DBus.Properties",
+                                     "Get",
+                                     g_variant_new ("(ss)", api->service_iface, "version"),
+                                     G_VARIANT_TYPE ("(v)"),
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL, &error);
+
+      if (reply == NULL)
+        g_debug ("Failed to get version: %s", error->message);
+      else
+        {
+          g_autoptr(GVariant) v = g_variant_get_child_value (reply, 0);
+          g_autoptr(GVariant) v2 = g_variant_get_variant (v);
+          version = g_variant_get_uint32 (v2);
+        }
+    }
+
+  return version;
+}
+
+static void
+check_portal_version (const char *option, guint32 version_needed)
+{
+  guint32 portal_version = get_portal_version ();
+  if (portal_version < version_needed)
+    {
+      g_printerr ("--%s not supported by host portal version (need version %d, has %d)\n", option, version_needed, portal_version);
+      exit (1);
+    }
+}
+
+static guint32
+get_portal_supports (void)
+{
+  static guint32 supports = 0;
+  static gboolean ran = FALSE;
+
+  g_return_val_if_fail (api != NULL, 0);
+  g_return_val_if_fail (api == &host_api || api == &subsandbox_api, 0);
+
+  if (!ran)
+    {
+      g_autoptr(GError) error = NULL;
+      g_autoptr(GVariant) reply = NULL;
+
+      ran = TRUE;
+
+      /* Support flags were added in version 3 */
+      if (get_portal_version () >= 3)
+        {
+          reply = g_dbus_connection_call_sync (bus_or_peer_connection,
+                                               api->service_bus_name,
+                                               api->service_obj_path,
+                                               "org.freedesktop.DBus.Properties",
+                                               "Get",
+                                               g_variant_new ("(ss)", api->service_iface, "supports"),
+                                               G_VARIANT_TYPE ("(v)"),
+                                               G_DBUS_CALL_FLAGS_NONE,
+                                               -1,
+                                               NULL, &error);
+          if (reply == NULL)
+            g_debug ("Failed to get supports: %s", error->message);
+          else
+            {
+              g_autoptr(GVariant) v = g_variant_get_child_value (reply, 0);
+              g_autoptr(GVariant) v2 = g_variant_get_variant (v);
+              supports = g_variant_get_uint32 (v2);
+            }
+        }
+    }
+
+  return supports;
+}
+
+static void
+check_portal_supports (const char *option, guint32 supports_needed)
+{
+  guint32 supports = get_portal_supports ();
+
+  if ((supports & supports_needed) != supports_needed)
+    {
+      g_printerr ("--%s not supported by host portal\n", option);
+      exit (1);
+    }
+}
+
 static gchar **forward_fds = NULL;
 static gboolean opt_clear_env = FALSE;
 static gchar *opt_dbus_address = NULL;
@@ -374,6 +482,7 @@ static gchar *opt_directory = NULL;
 static gchar *opt_socket = NULL;
 static GHashTable *opt_env = NULL;
 static GHashTable *opt_unsetenv = NULL;
+static gboolean opt_share_pids = FALSE;
 static gboolean opt_terminate = FALSE;
 static gboolean opt_verbose = FALSE;
 static gboolean opt_version = FALSE;
@@ -496,6 +605,9 @@ static const GOptionEntry options[] =
     G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, opt_env_cb,
     "Pass environment variables matching a shell-style wildcard.",
     "WILDCARD" },
+  { "share-pids", '\0',
+    G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_share_pids,
+    "Use same pid namespace as calling sandbox.", NULL },
   { "socket", '\0',
     G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_socket,
     "Connect to a Launcher server listening on this AF_UNIX socket.",
@@ -848,11 +960,25 @@ main (int argc,
                              g_variant_new_variant (g_variant_new_boolean (TRUE)));
     }
 
+  /* We just ignore this option when not using a subsandbox:
+   * host_api and launcher_api always share process IDs anyway */
+  if (opt_share_pids && api == &subsandbox_api)
+    {
+      check_portal_version ("share-pids", 5);
+      check_portal_supports ("share-pids", FLATPAK_SPAWN_SUPPORT_FLAGS_SHARE_PIDS);
+
+      spawn_flags |= FLATPAK_SPAWN_FLAGS_SHARE_PIDS;
+    }
+
   if (g_hash_table_size (opt_unsetenv) > 0)
     {
       g_hash_table_iter_init (&iter, opt_unsetenv);
 
-      if (api == &launcher_api)
+      /* The host portal doesn't support options, so we always have to do
+       * this the hard way. The subsandbox portal supports unset-env in
+       * versions >= 5. pressure-vessel-launcher always supports it. */
+      if (api == &launcher_api
+          || (api == &subsandbox_api && get_portal_version () >= 5))
         {
           GVariantBuilder strv_builder;