Skip to content
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

Terminal (non)blocking #588

Closed
hanche opened this issue Feb 6, 2018 · 7 comments
Closed

Terminal (non)blocking #588

hanche opened this issue Feb 6, 2018 · 7 comments
Labels

Comments

@hanche
Copy link
Contributor

hanche commented Feb 6, 2018

Once in a while, stdin ends up in a non-blocking state. Then this happens:

⬥ cat
cat: stdin: Resource temporarily unavailable
Exception: cat exited with 1
[tty], line 1: cat

Interestingly, exec bash followed by exec elvish resolves this when it happens. Easier is to run this little C program:

#include <fcntl.h>

int main(int argc, char*argv[]) {
	fcntl(0, F_SETFL, ~O_NONBLOCK & fcntl(0,F_GETFL));
	return 0;
}

and conversely, the issue can always be triggered by running the opposite program:

#include <fcntl.h>

int main(int argc, char*argv[]) {
	fcntl(0, F_SETFL, O_NONBLOCK | fcntl(0,F_GETFL));
	return 0;
}

Fish fixed a similar issue once. A similar fix to elvish may be a good idea. IOW, make sure the O_NONBLOCK flag is turned off on stdin before running an external command. As explained in the link, other shells don't do similar checks on stdout or stderr; perhaps because the problem is much less likely to happen there.

In case it's relevant, I had this issue on macos High Sierra. These lines from <sys/stdin.h> serve to explain the misleading error message:

#define EAGAIN          35              /* Resource temporarily unavailable */
#define EWOULDBLOCK     EAGAIN          /* Operation would block */

(Aside: I ran into the same issue with my old shell (es), and switched to elvish largely for that reason. Now I probably know enough to fix the problem in es and switch back, but I think I'll stay with elvish.)

@xiaq xiaq added the bug label Feb 6, 2018
@xiaq xiaq added this to the 0.12 milestone Mar 16, 2018
@xiaq
Copy link
Member

xiaq commented May 24, 2018

Sorry for the late followup, but which version of Elvish were you on and do you have a reliable way to reproduce this?

Elvish used to use nonblocking IO, but it has stopped doing so for quite a while. In fact, current HEAD of Elvish doesn't do any fnctl at all; we used to have a binding for fcntl but it was removed after nonblocking IO was no longer needed.

@hanche
Copy link
Contributor Author

hanche commented May 24, 2018

That was 0.11 (binary download for macOS). Sorry, I don't know a reliable way to reproduce. If anything, it seems to happen more rarely of late, but it still happens from time to time. I have not been able to figure out a pattern to it: It seems totally random.

@notramo
Copy link

notramo commented May 24, 2018

It can also happen when an external program exits while its file descriptors are non-blocking, and the editor don't modify the non-blocking flag before running the next command.

@hanche
Copy link
Contributor Author

hanche commented May 24, 2018

Indeed, that is what the second C program in my original post does. So in that sense, I know how to reproduce it. But what I don't know is if that is the only way it happens.

@zzamboni
Copy link
Contributor

I was able to reproduce this on master using @hanche's code:

> cat > test.c
#include <fcntl.h>

int main(int argc, char*argv[]) {
	fcntl(0, F_SETFL, O_NONBLOCK | fcntl(0,F_GETFL));
	return 0;
}
> gcc -o test test.c 
> ./test 
> cat
cat: -: Resource temporarily unavailable
Exception: cat exited with 1
[tty], line 1: cat
>

@xiaq
Copy link
Member

xiaq commented May 24, 2018

Well, if you manually put the terminal in nonblocking mode, it is certainly going to break programs... :)

Elvish itself does not manipulate the nonblocking flag of files at all. What could be the culprit though, is Go's builtin file poller, which will put files under nonblocking mode. If that's what is happening, fixing the issue will require understanding how the file poller works...

@xiaq xiaq removed this from the 0.13 milestone Apr 6, 2019
@hanche
Copy link
Contributor Author

hanche commented Aug 11, 2019

See also #822. Of course, nobody willingly leaves the terminal in nonblocking mode, except for testing purposes. But many programs do use nonblocking mode, and if such a program dies and is unable to turn blocking mode back on, elvish ought to be able to recover gracefully.

xiaq added a commit that referenced this issue Aug 11, 2019
@xiaq xiaq closed this as completed Aug 11, 2019
xiaq added a commit that referenced this issue Aug 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants