]> git.ipfire.org Git - thirdparty/git.git/commitdiff
simple-ipc: work around issues with Cygwin's Unix socket emulation
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Wed, 10 Nov 2021 11:09:10 +0000 (11:09 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Nov 2021 17:12:19 +0000 (09:12 -0800)
Cygwin emulates Unix sockets by writing files with custom contents and
then marking them as system files.

The tricky problem is that while the file is written and its `system`
bit is set, it is still identified as a file. This caused test failures
when Git is too fast looking for the Unix sockets and then complains
that there is a plain file in the way.

Let's work around this by adding a delayed retry loop, specifically for
Cygwin.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Tested-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/simple-ipc/ipc-unix-socket.c

index 4e28857a0a1e22aaa7538be2ef6d766a373dbca5..28a79289d4fd0a9d4e185cd5c9d8b19afdde70e7 100644 (file)
@@ -35,6 +35,28 @@ enum ipc_active_state ipc_get_active_state(const char *path)
                }
        }
 
+#ifdef __CYGWIN__
+       /*
+        * Cygwin emulates Unix sockets by writing special-crafted files whose
+        * `system` bit is set.
+        *
+        * If we are too fast, Cygwin might still be in the process of marking
+        * the underlying file as a system file. Until then, we will not see a
+        * Unix socket here, but a plain file instead. Just in case that this
+        * is happening, wait a little and try again.
+        */
+       {
+               static const int delay[] = { 1, 10, 20, 40, -1 };
+               int i;
+
+               for (i = 0; S_ISREG(st.st_mode) && delay[i] > 0; i++) {
+                       sleep_millisec(delay[i]);
+                       if (lstat(path, &st) == -1)
+                               return IPC_STATE__INVALID_PATH;
+               }
+       }
+#endif
+
        /* also complain if a plain file is in the way */
        if ((st.st_mode & S_IFMT) != S_IFSOCK)
                return IPC_STATE__INVALID_PATH;