Page MenuHome GnuPG

w32: Synchronous spawning gpg-agent/dirmngr/keyboxd
Open, WishlistPublic

Description

On POSIX machine, when gpg automatically invokes gpg-agent, it's done synchronously.

Currently, on Windows, it is done asynchronously and gpg frontend tries to connect to gpg-agent (with timeout).

Because it may takes loooong time like 20sec, it is good to do synchronous invocation on Windows too.

Event Timeline

gniibe triaged this task as Wishlist priority.Fri, Jul 11, 10:43 AM
gniibe created this task.

I'm testing the following patch with experimental change of libgpg-error.

diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index ae1295977..728aed1ab 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -1855,6 +1855,25 @@ main (int argc, char **argv)
         }
 
       log_info ("%s %s started\n", gpgrt_strusage(11), gpgrt_strusage(13) );
+#ifdef HAVE_W32_SYSTEM
+      {
+        int null_fd = open ("NUL", O_RDWR);
+
+        if (null_fd < 0)
+          {
+            perror ("open failed");
+            write (1, "ERR 1\n", 6);
+          }
+        else
+          {
+            write (1, "OK\n", 3);
+            if (dup2 (null_fd, 1) < 0)
+              perror ("dup2 failed");
+            dup2 (null_fd, 2);
+            close (null_fd);
+          }
+      }
+#endif
       handle_connections (fd, fd_extra, fd_browser, fd_ssh,
                           reliable_homedir_inotify);
       assuan_sock_close (fd);
diff --git a/common/asshelp.c b/common/asshelp.c
index 0152d1243..3c275c011 100644
--- a/common/asshelp.c
+++ b/common/asshelp.c
@@ -536,8 +536,39 @@ start_new_service (assuan_context_t *r_ctx,
           && assuan_socket_connect (ctx, sockname, 0, connect_flags))
         {
 #ifdef HAVE_W32_SYSTEM
+#if 0
           err = gpgrt_process_spawn (program? program : program_name, argv,
                                      GPGRT_PROCESS_DETACHED, NULL, NULL);
+#else
+          {
+            gpgrt_process_t proc;
+
+            err = gpgrt_process_spawn (program? program : program_name, argv,
+                                       (GPGRT_PROCESS_DETACHED
+                                        |GPGRT_PROCESS_STDOUT_PIPE
+                                        |GPGRT_PROCESS_STDERR_KEEP),
+                                       NULL, &proc);
+            if (!err)
+              {
+                int pipe_in;
+                err = gpgrt_process_get_fds (proc, 0, NULL, &pipe_in, NULL);
+                if (!err)
+                  {
+                    char buf[256];
+                    int r;
+                    r = read (pipe_in, buf, sizeof buf);
+                    close (pipe_in);
+                    if (r < 0)
+                      {
+                        log_error ("read from child process failed: %s\n",
+                                   strerror (errno));
+                        err = gpg_error (GPG_ERR_SERVER_FAILED);
+                      }
+                  }
+                gpgrt_process_release (proc);
+              }
+          }
+#endif
 #else /*!W32*/
           err = gpgrt_process_spawn (program? program : program_name, argv,
                                      0, NULL, NULL);
diff --git a/common/stringhelp.c b/common/stringhelp.c
index 9a2265258..6596c65cd 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -70,6 +70,22 @@ change_slashes (char *name)
 {
 #ifdef HAVE_DOSISH_SYSTEM
   char *p;
+  /* 0: don't know yet, 1: it's under wine, -1: no */
+  static int semihosted_by_wine;
+
+  /* Under wine, no change.  */
+  if (!semihosted_by_wine)
+    {
+      HMODULE hntdll = GetModuleHandle ("ntdll.dll");
+      if (hntdll
+          && GetProcAddress (hntdll, "wine_get_version"))
+        semihosted_by_wine = 1;
+      else
+        semihosted_by_wine = -1;
+    }
+
+  if (semihosted_by_wine > 0)
+    return name;
 
   if (strchr (name, '\\'))
     {
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index d418d09e2..d8e5f8da5 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -1526,6 +1526,23 @@ main (int argc, char **argv)
       pid = getpid ();
       es_printf ("set %s=%s;%lu;1\n",
                  DIRMNGR_INFO_NAME, socket_name, (ulong) pid);
+      {
+        int null_fd = open ("NUL", O_RDWR);
+
+        if (null_fd < 0)
+          {
+            perror ("open failed");
+            write (1, "ERR 1\n", 6);
+          }
+        else
+          {
+            write (1, "OK\n", 3);
+            if (dup2 (null_fd, 1) < 0)
+              perror ("dup2 failed");
+            dup2 (null_fd, 2);
+            close (null_fd);
+          }
+      }
 #else
       pid = fork();
       if (pid == (pid_t)-1)
diff --git a/kbx/keyboxd.c b/kbx/keyboxd.c
index 197f01c74..842661327 100644
--- a/kbx/keyboxd.c
+++ b/kbx/keyboxd.c
@@ -735,6 +735,23 @@ main (int argc, char **argv )
       (void)nodetach;
       initialize_modules ();
 
+      {
+        int null_fd = open ("NUL", O_RDWR);
+
+        if (null_fd < 0)
+          {
+            perror ("open failed");
+            write (1, "ERR 1\n", 6);
+          }
+        else
+          {
+            write (1, "OK\n", 3);
+            if (dup2 (null_fd, 1) < 0)
+              perror ("dup2 failed");
+            dup2 (null_fd, 2);
+            close (null_fd);
+          }
+      }
 #else /*!HAVE_W32_SYSTEM*/
 
       pid = fork ();