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

Re: Funny: git -p submodule summary

From
Jeff King <peff@peff.net>
Date
Jan 9, 2009, 08:38 UTC
Message-ID
<20090109083836.GB21389@coredump.intra.peff.net>
In-Reply-To
<alpine.DEB.1.00.0901081601240.30769@pacific.mpi-cbg.de>
On Thu, Jan 08, 2009 at 04:07:08PM +0100, Johannes Schindelin wrote:
Show 8 quoted lines
> Just try this with a submodule that has more changes than fit on a screen:
> 
> 	$ git -p submodule summary
> 
> In my tests, it consistently fscks up my console.  I wonder if this is 
> related to ea27a18(spawn pager via run_command interface).
> 
> *reverts that commit* Yep, that fixes it.
Hmm. I can reproduce your problem here, like this:
  $ git -p submodule summary
but when I tried to dig deeper using strace, the problem goes away:
  $ strace -f -o foo.out git -p submodule summary
However, I was able to get some data by stracing _just_ less:
  $ GIT_PAGER='strace -f -o foo.out less' git -p submodule summary
and that reproduces the problem. And here's the interesting bit:
  open("/dev/tty", O_RDONLY|O_LARGEFILE)  = 3
  ...
  read(0, $SOME_SUBMODULE_OUTPUT, ...)
  write(1, $SOME_SUBMODULE_OUTPUT, ...)
  read(3, 0xbfd3442f, 1)                  = -1 EIO (Input/output error)

That is, after displaying the actual output, the next thing less does is try to get input from the user on /dev/tty. But it returns EIO. At which point less just dies, leaving your terminal in a funny state.

Hrm. Here's a theory. The new pager behavior goes something like this for a builtin:

  1. fork, child becomes pager
  2. register atexit handler to wait for pager to finish
  3. run builtin
  4. exit, triggering handler

but for an external command (like a shell script), we exec the command, and presumably forget about out atexit handler entirely. Which means that our shell script writes all of its output and exits before less has a chance to prompt and get a response from the tty.

And I'll admit to being very hazy on the details of process groups and controlling terminals, but from what I recall, perhaps the EIO is related to the process group leader being dead. Which means we could paper over it by putting less in its own pgrp.

So here's a little test (in bash):
  $ set +m ;# disable job control, leaving bash as the pgrp leader
  $ git -p submodule summary

A-ha. That "works" in the sense that less runs fine and show the output. So it is a pgrp issue. _But_ we still have a problem, which is that the original process has exited, and bash thinks the command is finished. So now annoyingly we have both bash and less trying to read from the terminal.

So the _real_ problem is that we are not always triggering the "wait for pager to finish" code because we exec and forget about it. Which means this strategy of "git runs child pager" will never work properly. Instead, we have to use three processes: git and the pager become child processes, while the original process waits for both to exit and returns the proper exit code from git.

Let me try to work up a patch.
-Peff
PS I believe this is related to a similar bug which I have been hunting
   fruitlessly for a few weeks: if you use ^C to kill git, the pager
   will sometimes do funny things. I also traced that to an EIO on
   reading from the terminal, which makes sense: we are killing git
   before it gets a chance to do wait_for_pager.
Previous: Johannes SchindelinNext: Jeff King
Message 3 of 41 in “Funny: git -p submodule summary”
  1. Johannes SchindelinJan 8, 2009
  2. Johannes SchindelinJan 8, 2009
  3. Jeff KingJan 9, 2009
  4. Jeff KingJan 9, 2009
  5. Jeff KingJan 9, 2009
  6. Johannes SixtJan 9, 2009
  7. Jeff KingJan 9, 2009
  8. Johannes SixtJan 9, 2009
  9. Jeff KingJan 9, 2009
  10. Jeff KingJan 11, 2009
  11. 1/4 Makefile: clean up TEST_PROGRAMS definitionJeff King, Jan 11, 2009
  12. 2/4 chain kill signals for cleanup functionsJeff King, Jan 11, 2009
  13. Jeff KingJan 11, 2009
  14. 3/4 refactor signal handling for cleanup functionsJeff King, Jan 11, 2009
  15. 4/4 pager: do wait_for_pager on signal deathJeff King, Jan 11, 2009
  16. Junio C HamanoJan 11, 2009
  17. Johannes SixtJan 12, 2009
  18. Jeff KingJan 12, 2009
  19. Johannes SixtJan 12, 2009
  20. Jeff KingJan 12, 2009
  21. Johannes SixtJan 12, 2009
  22. Junio C HamanoJan 9, 2009
  23. Jeff KingJan 9, 2009
  24. Junio C HamanoJan 9, 2009
  25. 0/3 fix "Funny: git -p submodule summary"Jeff King, Jan 27, 2009
  26. 1/3 git: s/run_command/run_builtin/Jeff King, Jan 27, 2009
  27. 2/3 run_command: handle missing command errors more gracefullyJeff King, Jan 27, 2009
  28. 3/3 git: use run_command to execute dashed externalsJeff King, Jan 27, 2009
  29. Johannes SixtJan 27, 2009
  30. Jeff KingJan 27, 2009
  31. Johannes SixtJan 27, 2009
  32. Jeff KingJan 28, 2009
  33. Johannes SchindelinJan 27, 2009
  34. Jeff KingJan 28, 2009
  35. 1/4 git: s/run_command/run_builtin/Jeff King, Jan 28, 2009
  36. 2/4 run_command: handle missing command errors more gracefullyJeff King, Jan 28, 2009
  37. 3/4 run-command: help callers distinguish errorsJeff King, Jan 28, 2009
  38. Jeff KingJan 28, 2009
  39. Jeff KingJan 28, 2009
  40. 4/4 git: use run_command to execute dashed externalsJeff King, Jan 28, 2009
  41. Junio C HamanoJan 28, 2009

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.