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

Re: [PATCH v2 3/3] mingw: replace isatty() hack

From
Johannes Sixt <j6t@kdbg.org>
Date
Dec 22, 2016, 22:28 UTC
Message-ID
<04859cf9-e67a-28ab-ccb3-249687e696c8@kdbg.org>
In-Reply-To
<alpine.DEB.2.20.1612222235200.155951@virtualbox>
Am 22.12.2016 um 22:37 schrieb Johannes Schindelin:
Show 56 quoted lines
> Hi Hannes,
>
> On Thu, 22 Dec 2016, Johannes Sixt wrote:
>
>> Am 22.12.2016 um 18:09 schrieb Johannes Schindelin:
>>> +static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
>>> +{
>>> +	/*
>>> +	 * Create a copy of the original handle associated with fd
>>> +	 * because the original will get closed when we dup2().
>>> +	 */
>>> +	HANDLE handle = (HANDLE)_get_osfhandle(fd);
>>> +	HANDLE duplicate = duplicate_handle(handle);
>>>
>>> +	/* Create a temp fd associated with the already open "new_handle". */
>>> +	int new_fd = _open_osfhandle((intptr_t)new_handle, O_BINARY);
>>>
>>> +	assert((fd == 1) || (fd == 2));
>>>
>>> +	/*
>>> +	 * Use stock dup2() to re-bind fd to the new handle.  Note that
>>> +	 * this will implicitly close(1) and close both fd=1 and the
>>> +	 * originally associated handle.  It will open a new fd=1 and
>>> +	 * call DuplicateHandle() on the handle associated with new_fd.
>>> +	 * It is because of this implicit close() that we created the
>>> +	 * copy of the original.
>>> +	 *
>>> +	 * Note that the OS can recycle HANDLE (numbers) just like it
>>> +	 * recycles fd (numbers), so we must update the cached value
>>> +	 * of "console".  You can use GetFileType() to see that
>>> +	 * handle and _get_osfhandle(fd) may have the same number
>>> +	 * value, but they refer to different actual files now.
>>
>> Certainly, the OS does not recycle handle values that are in use (open). Then
>> I do not quite get the point of this paragraph. See...
>>
>>> +	 *
>>> +	 * Note that dup2() when given target := {0,1,2} will also
>>> +	 * call SetStdHandle(), so we don't need to worry about that.
>>> +	 */
>>> +	dup2(new_fd, fd);
>>> +	if (console == handle)
>>> +		console = duplicate;
>>
>> ... This is where "the cached value of console is updated", right? If console
>> == handle, then this is not because a handle value was recycled, but because
>> fd *was* console. Since the old value of console has been closed by the
>> dup2(), we must refer to the back-up value in the future. Am I missing
>> something?
>
> You are correct, we must update `console` because `handle` is no longer
> the handle we want.
>
> The comment above only meant to reinforce that we have to forget about the
> previous handle, too, as we might access something completely different
> than a console otherwise.
It is like accessing a pointer after free().

When I read the paragraph for the first time, I expected some information to be saved, then some handles to be closed and re-opened, which would possibly recycle a handle value, and then same state to be resurrected depending on the information saved earlier.

But nothing of this kind happens, only:
	dup2(new_fd, fd);
	if (console == handle)
		console = duplicate;
which is necessary and, once one has understood the context, obvious.
> Would you have a suggestion how to rephrase the comment to make it less
> confusing?
Perhaps
	 * This might close the cached console handle.
	 * We must cache the live duplicate instead.

Then update the cache before the dup2, because at this time all 3 of console, handle, and duplicate are live and cannot be recycled:

	if (console == handle)
		console = duplicate;
	dup2(new_fd, fd);
-- Hannes
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 14 of 29 in “Really fix the isatty() problem on Windows”
  1. 0/2 Really fix the isatty() problem on WindowsJohannes Schindelin, Dec 21, 2016
  2. 1/2 mingw: adjust is_console() to work with stdinJohannes Schindelin, Dec 21, 2016
  3. 2/2 mingw: replace isatty() hackJohannes Schindelin, Dec 21, 2016
  4. Junio C HamanoDec 21, 2016
  5. Johannes SixtDec 21, 2016
  6. Junio C HamanoDec 21, 2016
  7. Johannes SixtDec 22, 2016
  8. Johannes SchindelinDec 22, 2016
  9. 0/3 Really fix the isatty() problem on WindowsJohannes Schindelin, Dec 22, 2016
  10. 2/3 mingw: fix colourization on Cygwin pseudo terminalsJohannes Schindelin, Dec 22, 2016
  11. 3/3 mingw: replace isatty() hackJohannes Schindelin, Dec 22, 2016
  12. Johannes SixtDec 22, 2016
  13. Johannes SchindelinDec 22, 2016
  14. Johannes SixtDec 22, 2016
  15. Johannes SchindelinDec 22, 2016
  16. 1/3 mingw: adjust is_console() to work with stdinJohannes Schindelin, Dec 22, 2016
  17. Beat BolliDec 22, 2016
  18. Junio C HamanoDec 22, 2016
  19. Johannes SchindelinDec 23, 2016
  20. Beat BolliDec 23, 2016
  21. Junio C HamanoDec 22, 2016
  22. Johannes SchindelinDec 22, 2016
  23. Junio C HamanoDec 22, 2016
  24. Junio C HamanoDec 22, 2016
  25. 0/3 Really fix the isatty() problem on WindowsJohannes Schindelin, Dec 22, 2016
  26. 1/3 mingw: adjust is_console() to work with stdinJohannes Schindelin, Dec 22, 2016
  27. 2/3 mingw: fix colourization on Cygwin pseudo terminalsJohannes Schindelin, Dec 22, 2016
  28. 3/3 mingw: replace isatty() hackJohannes Schindelin, Dec 22, 2016
  29. Johannes SchindelinJan 18, 2017

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.