-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
using stdio can hit unreachable on systems that are mostly POSIX #2428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is not a bug... POSIX does say that stdin/stdout/stderr are present in new processes. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html
What you're seeing is a place where linux (and other OSes) allow you to break POSIX assurances. |
I contend that it is still a bug because both |
Ah, I was replying to the original title:
|
I don't think it's obvious how (or whether) to solve this. I agree with @tgschultz that since However, I also want to note that the error in the original post comes from the One possibility is to put code before main() that does syscalls to test stdin/stdout/stderr file descriptors, but that's not desirable for obvious reasons. |
My question on IRC was, why it does not fail on getStdOut() even so the comment suggests otherwise. |
The current reason for the possibility of failure is Windows: https://docs.microsoft.com/en-us/windows/console/getstdhandle |
So Also maybe the comment should be changed so it doesn't give the wrong impression? |
I think the correct fix is to simply change
|
glibc does this. It is ugly however.
Not with |
Proposal: change the title of this issue to Attempting to write to stdin makes no sense anyways. The real issue isn't that Zig is hitting unreachable under POSIX, it's that the POSIX backend - which would never hit that error on a fully POSIX system - can and indeed should run on systems that don't fully meet POSIX, though what to do there isn't so clearcut as "return an error." |
On a more practical note: I'd contend that the current behavior is correct. The only situation under which this error can occur is if you deliberately make the platform not POSIX-compatible. I'm personally not okay with adding OS-specific changes to the POSIX backend, and adding a Linux-specific backend would be a tremendous waste of time and effort. As is, the produced executable is a POSIX application just as much as a Linux one (referring just to the standard library here). The fact that you then twist the running environment to not be POSIX isn't a problem, but to then expect a POSIX executable to run makes no sense. If a Windows executable refuses to run under Windows because it contains code that is only valid under WINE, the onus to fix the issue would not be on Zig (though I'm unsure if that's actually ever possible). |
I was going to propose a solution, but then a thought occured: if you close a stdio stream, will a future call to If it's possible under Linux, but not POSIX, then it's a bit trickier. Checking if they're open before calling |
More reading: https://stackoverflow.com/a/25516438 |
We have to live with the kernel binaries that exist, not some human-language standards. |
Yes, but this isn't a Linux backend, it's a POSIX one. If this is unreachable under, say, OS X (AFAICT it's not) or WASI (no clue), then it makes sense to adhere to the standard and require OS-specific support to prevent you from getting there. However, there's a more pressing reason that I think the current situation can't stand (though I'm not convinced returning an error is the correct solution): Since it's possible to close stdio streams, a very important question is raised: if stdio is closed, should we care? More generally, if someone either redirects it (see OP), or closes it later, and then tries writing to it, what should happen? There are definitely valid arguments to be made for returning an error, panicking, etc. But here's a "fun" little example that I think pushes me to the side of "return an error." // Externally defined function which closes stdout and stderr
extern fn close_stdio_streams();
pub fn main() void {
close_stdio_streams();
import("std").debug.warn("Hello!");
} |
More importantly, if you deliberately create an environment in which applications won't function correctly, and then they don't, that's on you, not the OS, and not the application. The real crux of this issue is that it will only ever happen if you want it to. If you close stdio and then try using it, that's your choice, but I'd argue that that's inherently library-level UB, no different from e.g. addition overflow or pointer comparison in C. |
I think it's correct for Zig to treat the hard-coded file descriptor values 0, 1, and 2 as stdio. I'm pretty sure this issue is going to end up being closed with working-as-designed. |
In that case, does it make sense to have os.close fail/panic if given [0..2]? |
Nope, it's the programmer's responsibility to deal with the fact that 0, 1, 2 are aliased with stdio. If the kernel allows applications to close stdio file descriptors and open new ones, the programmer may do it, and if they choose to do this then they have opted into dealing with it. |
Yeah, that makes sense. |
I'm pretty confident that will be the best approach. |
Note: POSIX only says that new processes will be started with a std{out/in/err}. Processes are allowed to close them; open new fds on them; |
FWIW, I recently had an issue in a C library I created and maintain and in it I was closing a file descriptor which happened to be 0 (zero). It turned out that MQTT (I think, need to look at the bug again) was using this. It was on some IoT platform. Long story short, 0 was not stdin so my bug of closing what should have been an unopened file descriptor closed down the MQTT library. Oops. Now my library relies on a fair amount of POSIX stuff so the platform was POSIX-ish. Perhaps moot, but it is a data point. |
El sáb., 21 dic. 2019 6:22, Kyle Hayes <[email protected]> escribió:
Perhaps moot, but it is a data point.
No. This is exactly how these things are. If there is some customary way of
using an interface, and a similar interface is implemented, that custom
must be implemented faithfully or not implemented at all and those IDs that
may cause confusion to not be used. He fd namespace is big enough that
these first 4 could have been avoided, and the platform is in the wrong.
|
This whole thing shouldn't be about POSIX, it should be about Zig.
Completely agree. But in the case demonstrated, the caller starting the application has closed the file descriptors. I just want to be able to handle this case in my applications. If the argument is about POSIX, it could be argued that this should be ensured by the kernel. But as far as I know, POSIX deals with the operating system (!= kernel) interface and does not define which part of the OS ensures some capability (https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap01.html):
If Zig really wants to hold true to the following stated characteristics
, there should be a way to deal with this. Also if Zig wants to replace C, which is an integral part of POSIX specification, Zig should not rely on POSIX features/behaviors and deal with kernel specific characteristics. |
Modify your code to deal with the situation and everything works fine. If you don't want to call |
I do think a way to detect this would be useful though. The problem here is that e.g. std.debug.warn will still panic. There is at present no good way of checking if the stdio FDs are valid. I think that returning an error instead of unreachable might not be ideal, but the fact remains that there are multiple systems on which this is, arguably, correct. Both MacOS and Linux can hit that unreachable. Furthermore, as has been pointed out both by daurminator and myself, it is valid under POSIX to close them. As such, I think we should be returning an error here.
The problem is that this isn't a matter of opting in. As Camerin mentioned,
If you didn't choose this, you should still be able to deal with it. |
Uh oh!
There was an error while loading. Please reload this page.
As submitted by cameris in IRC:
The text was updated successfully, but these errors were encountered: