git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: t0301-credential-cache test failure on cygwin

From
Jeff King <peff@peff.net>
Date
Jul 13, 2022, 19:16 UTC
Message-ID
<Ys8aJ1HSLnWFT5qB@coredump.intra.peff.net>
In-Reply-To
<CA+kUOam-_3qR7YguPyUmyC2dWi2M1cy6Hg4Pveak+f40qtYBvA@mail.gmail.com>
On Wed, Jul 13, 2022 at 03:42:38PM +0100, Adam Dinwoodie wrote:
Show 5 quoted lines
> Having now spent far more time than I'd like wrangling the Cygwin build
> infrastructure, I've found the change in the Cygwin code that introduced
> the break. But I'm afraid progressing beyond this -- and in particular
> making any sort of judgement about appropriate next steps -- is beyond
> what I'm going to have time for in the foreseeable future.

Hmm. So I had assumed that the problem was unlink()ing the socket path while the client was still trying to read(). If that's the case, then I _think_ the minimal reproduction below should also trigger the problem. That might give you something more useful to show to Cygwin folks.

But...
Show 17 quoted lines
> commit ef95c03522f65d5956a8dc82d869c6bc378ef3f9 (HEAD, refs/bisect/bad)
> Author: Corinna Vinschen <corinna@vinschen.de>
> Date:   Tue Apr 6 21:35:43 2021 +0200
> 
>     Cygwin: select: Fix FD_CLOSE handling
>     
>     An FD_CLOSE event sets a socket descriptor ready for writing.
>     This is incorrect if the FD_CLOSE is a result of shutdown(SHUT_RD).
>     Only set the socket descriptor ready for writing if the FD_CLOSE
>     is indicating an connection abort or reset error condition.
>     
>     This requires to tweak fhandler_socket_wsock::evaluate_events.
>     FD_CLOSE in conjunction with FD_ACCEPT/FD_CONNECT special cases
>     a shutdown condition by setting an error code.  This is correct
>     for accept/connect, but not for select.  In this case, make sure
>     to return with an error code only if FD_CLOSE indicates a
>     connection error.

...this is about select outcomes. Which makes me think two things (though these are really pretty blind guesses, as I'm not at all familiar with Cygwin's socket code):

  - it may be that this situation was always ECONNABORTED (it's not on
    Linux, but perhaps due to details of the underlying socket code on
    Windows, it's different there). And this patch is just surfacing
    that state to the caller better.
  - it could be unrelated to the unlink() entirely. The socket code in
    Git dups the client descriptor and opens two FILE* handles, one for
    reading and one for writing. Could it be that it's important to
    fclose() one before the other (and the implicit closing done by
    exit() does the wrong order)? It seems like a stretch, but this
    commit message is talking about a shutdown(SHUT_RD), which is kind
    of what you get by fclose-ing one side (though again, not on Linux,
    because the "FILE*" are aware that they are read/write, but the
    underlying descriptors aren't).

Or maybe those are just totally off track. I know you said you don't have time to dig further, and that's fine. But if you or anybody has a chance to try the program below, it might be interesting to see the result (it would confirm whether it's the unlink() that's the problem).

-- >8 -- #include <stdio.h> #include <stdlib.h>

#include <unistd.h> #include <sys/socket.h> #include <sys/un.h>

#define SOCKET_PATH "mysocket"
static void diesys(const char *syscall)
{
	perror(syscall);
	exit(1);
}
static int create_server(void)
{
	int fd;
	struct sockaddr_un sa = {
		.sun_family = AF_UNIX,
		.sun_path = SOCKET_PATH,
	};
	fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (fd < 0)
		diesys("socket");
	if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
		diesys("bind");
	if (listen(fd, 5) < 0)
		diesys("listen");
	return fd;
}
static void do_server(int listen_fd)
{
	int client_fd = accept(listen_fd, NULL, NULL);
	if (client_fd < 0)
		diesys("accept");
	if (unlink(SOCKET_PATH) < 0)
		diesys("unlink");
	if (close(client_fd) < 0)
		diesys("close(client)");
	close(listen_fd);
}
static void do_client(void)
{
	int fd;
	char buf[64];
	struct sockaddr_un sa = {
		.sun_family = AF_UNIX,
		.sun_path = SOCKET_PATH,
	};
	fd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (fd < 0)
		diesys("socket");
	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
		diesys("connect");
	if (read(fd, buf, sizeof(buf)) < 0)
		diesys("read");
	close(fd);
}
int main(void)
{
	int fd = create_server();
	if (fork()) {
		do_server(fd);
	} else {
		close(fd);
		do_client();
	}
	return 0;
}
Previous: Adam DinwoodieNext: Ramsay Jones
Message 11 of 15 in “t0301-credential-cache test failure on cygwin”
  1. Ramsay JonesJul 7, 2022
  2. Junio C HamanoJul 7, 2022
  3. Ramsay JonesJul 7, 2022
  4. Jeff KingJul 7, 2022
  5. Jeff KingJul 7, 2022
  6. Ramsay JonesJul 7, 2022
  7. Adam DinwoodieJul 11, 2022
  8. Adam DinwoodieJul 11, 2022
  9. Ramsay JonesJul 11, 2022
  10. Adam DinwoodieJul 13, 2022
  11. Jeff KingJul 13, 2022
  12. Ramsay JonesJul 13, 2022
  13. Jeff KingJul 7, 2022
  14. Junio C HamanoJul 7, 2022
  15. Ramsay JonesJul 7, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.