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

Re: [RFC] upload-pack deadlock

From
Junio C Hamano <gitster@pobox.com>
Date
Apr 6, 2011, 17:20 UTC
Message-ID
<7v8vvnjnyg.fsf@alter.siamese.dyndns.org>
In-Reply-To
<20110404053626.GA26529@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
Show 26 quoted lines
> In a pthread-enabled version of upload-pack, there's a race condition
> that can cause a deadlock on the fflush(NULL) we call from run-command.
>
> What happens is this:
>
>   1. Upload-pack is informed we are doing a shallow clone.
>
>   2. We call start_async() to spawn a thread that will generate rev-list
>      results to feed to pack-objects. It gets a file descriptor to a
>      pipe which will eventually hook to pack-objects.
>
>   3. The rev-list thread uses fdopen to create a new output stream
>      around the fd we gave it, called pack_pipe.
>
>   4. The thread writes results to pack_pipe. Outside of our control,
>      libc is doing locking on the stream. We keep writing until the OS
>      pipe buffer is full, and then we block in write(), still holding
>      the lock.
>
>   5. The main thread now uses start_command to spawn pack-objects.
>      Before forking, it calls fflush(NULL) to flush every stdio output
>      buffer. It blocks trying to get the lock on pack_pipe.
>
> And we have a deadlock. The thread will block until somebody starts
> reading from the pipe. But nobody will read from the pipe until we
> finish flushing to the pipe.
Thanks for a concise summary.
Show 6 quoted lines
> There are a few possible solutions:
>
>   1. Flip the order of initialization, so that we don't start writing
>      anything until the pack-objects reader is already in place. That
>      works in this case, and the patch is at the end of this mail. The
>      biggest problem is that it doesn't fix the general case.
In what sense are you not fixing "the general case", though?

If a program runs two threads, both of which access the FILE streams, it should be the responsibility of the program to get these threads coordinated to avoid such races and deadlocks, no?

While I think you mean start_async() API should be helping the API users (calling programs) to fulfil that responsibility better, it really is up to the thread to do random things to wreak havoc, like the shallow codepath that tries to fill the stream while the main codepath expected nothing happening, and I do not think of a good abstraction to help us being more careful.

Previous: Jeff KingNext: Jeff King
Message 2 of 10 in “[RFC] upload-pack deadlock”
  1. Jeff KingApr 4, 2011
  2. Junio C HamanoApr 6, 2011
  3. Jeff KingApr 6, 2011
  4. Erik Faye-LundApr 6, 2011
  5. Jeff KingApr 6, 2011
  6. Jeff KingApr 6, 2011
  7. Jonathan NiederApr 18, 2011
  8. [1.7.2] Please cherry-pick "upload-pack: start pack-objects before async rev-list"Jonathan Nieder, May 26, 2011
  9. Junio C HamanoMay 26, 2011
  10. Jonathan NiederMay 26, 2011

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.