Spooky tmux at a Distance: Difference between revisions
No edit summary |
em dashes! |
||
| Line 37: | Line 37: | ||
* When a newline is written, if the stream is line buffered. | * When a newline is written, if the stream is line buffered. | ||
* Whenever an input operation on any stream actually reads data from its file.</blockquote> | * Whenever an input operation on any stream actually reads data from its file.</blockquote> | ||
anaphora aside, that's pretty exhaustive. read that last line again. '''Whenever an input operation on any stream actually reads data from its file.''' in GNU libc (again, this is '''not''' part of ANSI | anaphora aside, that's pretty exhaustive. read that last line again. '''Whenever an input operation on any stream actually reads data from its file.''' in GNU libc (again, this is '''not''' part of ANSI C—though not prohibited, either), any successful read operation (this does '''not''' apply to the <tt>read(2)</tt> system call, despite being wrapped by glibc), ''on any <tt>FILE*</tt>'', flushes all buffered output data. | ||
is this the [https://en.wikipedia.org/wiki/Principle_of_least_astonishment Least Astonishing] thing it could do? no it is not. christ, what a waste of my time. and in what ways does this complicate multithreading? | is this the [https://en.wikipedia.org/wiki/Principle_of_least_astonishment Least Astonishing] thing it could do? no it is not. christ, what a waste of my time. and in what ways does this complicate multithreading? | ||
| Line 59: | Line 59: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
the third parameter to <tt>term_emit()</tt> controlled flushery, and our third call flushes, and the world is good, right? well of course | the third parameter to <tt>term_emit()</tt> controlled flushery, and our third call flushes, and the world is good, right? well of course not—that <tt>term_emit()</tt> was conditional on <tt>nc->tcache.oc</tt>. and guess what terminal definition lacks <tt>oc</tt>? here's a hint: it starts with t and rhymes with "fucks". furthermore, <tt>term_emit()</tt> writes to <tt>nc->ttyfp</tt>, a stdio <tt>FILE*</tt>, while <tt>tty_emit()</tt> writes to a file descriptor, and requires actually being attached to a terminal (there's precious little value in, say, clearing the screen when you're writing to a file or pipe). so there are at least 4 bugs in these 14 lines. put another way, the only bug-free operative lines of code are <tt>int ret = 0;</tt>, <tt>ret = -1;</tt>, and <tt>return ret;</tt>. | ||
dijkstra is looking down at me from Dutch heaven, frowning, slowly chewing a De Ruijter Fruit Sprinkle as he ruminates, wincing a time or two, and finally declaring "i do not like it." he's not referring to the Sprinkle, of which he is reservedly fond. | dijkstra is looking down at me from Dutch heaven, frowning, slowly chewing a De Ruijter Fruit Sprinkle as he ruminates, wincing a time or two, and finally declaring "i do not like it." he's not referring to the Sprinkle, of which he is reservedly fond. | ||
| Line 66: | Line 66: | ||
* <tt>tmux</tt>, alone among tested terminals, did not declare <tt>oc</tt>. everything else flushed the reset early on, as intended, hiding the bug. | * <tt>tmux</tt>, alone among tested terminals, did not declare <tt>oc</tt>. everything else flushed the reset early on, as intended, hiding the bug. | ||
* a bug of mine meant that the reset was written using stdio, though admittedly this is merely a side- | * a bug of mine meant that the reset was written using stdio, though admittedly this is merely a side-effect—the real bug was emitting control sequences to a non-terminal. this bug would otherwise not have been an issue, as <tt>write(2)</tt> is of course unbuffered. | ||
* if the banners were used, they flushed stdout (by virtue of writing a newline), hiding the bug. | * if the banners were used, they flushed stdout (by virtue of writing a newline), hiding the bug. | ||
* stdout was not otherwise explicitly touched during the course of execution, but this unknown, supra-Standard behavior implied a buffer flush in an unrelated <tt>getc(3)</tt>. | * stdout was not otherwise explicitly touched during the course of execution, but this unknown, supra-Standard behavior implied a buffer flush in an unrelated <tt>getc(3)</tt>. | ||