Navigation Menu

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

Unix.select raises EINVAL incorrectly #7700

Closed
vicuna opened this issue Dec 27, 2017 · 7 comments
Closed

Unix.select raises EINVAL incorrectly #7700

vicuna opened this issue Dec 27, 2017 · 7 comments

Comments

@vicuna
Copy link

vicuna commented Dec 27, 2017

Original bug ID: 7700
Reporter: gabelevi
Status: acknowledged (set by @dra27 on 2017-12-27T20:21:03Z)
Resolution: open
Priority: normal
Severity: minor
Platform: unix
Version: 4.00.1
Target version: 4.07.0+dev/beta2/rc1/rc2
Category: standard library
Monitored by: antron @nojb @dbuenzli

Bug description

Unix.select's c implementation will raise EINVAL if any fd passed in is less than 0 or greater or equal to FD_SETSIZE (

if (retcode != 0) unix_error(EINVAL, "select", Nothing);
). This behavior was introduced in #5563

The main problem is that select should raise EBADF for invalid file descriptors.

Assuming that there are valid fds which are greater than or equal to FD_SETSIZE, perhaps a better behavior would be

  • If fd is less than 0, then raise EBADF
  • If fd is greater than or equal to FD_SETSIZE, then check if it is a valid fd. Raise EBADF on an invalid fd and EINVAL otherwise

Steps to reproduce

I found this issue by looking at stack traces in some of my logs. It should be pretty easy to reproduce, though, by crafting an invalid fd < 0 or >= FD_SETSIZE and passing it to Unix.select.

Additional information

I encountered this using lwt, which explicitly handles EBADF and filters out bad fds: https://github.com/ocsigen/lwt/blob/5b61d2a0e18b47ec82dfc61ce0bcb68f4a3945c7/src/unix/lwt_engine.ml#L364

@vicuna
Copy link
Author

vicuna commented Dec 27, 2017

Comment author: gabelevi

Assuming that there are valid fds which are greater than or equal to FD_SETSIZE

Since FD_SETSIZE is pretty low (1024), this should be a safe assumption. It's probably the common case too, though I think EINVAL is still non-standard for this case.

@vicuna
Copy link
Author

vicuna commented Dec 27, 2017

Comment author: @dra27

Passing an fd which is >= FD_SETSIZE is undefined behaviour. Can we not usefully do the simplest patch, which is just to return EBADF instead of EINVAL in all cases? It sounds like in Lwt's case, this would result in a reasonable course of action (filtering out the fd)?

@vicuna
Copy link
Author

vicuna commented Dec 27, 2017

Comment author: @dra27

Open Group reference: http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html

@vicuna
Copy link
Author

vicuna commented Dec 27, 2017

Comment author: gabelevi

My guess is that almost everyone who gets Unix.Unix_error(EINVAL, "select", "") has too many fds open and is passing in some valid fd >= FD_SETSIZE. Since the behavior for fds < 0 or >= FD_SETSIZE is undefined, it might be best for developer ergonomics to throw a descriptive exception that doesn't overlap with anything that select() might throw.

I suppose EBADF won't necessarily fix the Lwt case, since valid fds >= FD_SETSIZE won't be filtered out with their fstat check.

@vicuna
Copy link
Author

vicuna commented Dec 27, 2017

Comment author: gabelevi

Of course, changing the exceptional behavior might be a breaking change for anyone relying on it...

@vicuna
Copy link
Author

vicuna commented Dec 28, 2017

Comment author: @dra27

Well, I think we could refine it that having an fd >= FD_SETSIZE means either that you are leaking fds or you should be using poll. With that in mind, another idea could be to raise Invalid_argument for the >= FD_SETSIZE case (and not care about whether the fd is actually valid in this case), but that could only be done if we add a function like can_select of type file_descr list -> bool.

It's worth cross-referencing #1514 (#1514), as we recently rejected changing Unix.select to be implemented using poll.

@vicuna vicuna added the stdlib label Mar 14, 2019
@vicuna vicuna added this to the 4.07.0 milestone Mar 14, 2019
@vicuna vicuna added the bug label Mar 20, 2019
@github-actions
Copy link

github-actions bot commented May 7, 2020

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

@github-actions github-actions bot added the Stale label May 7, 2020
@github-actions github-actions bot closed this as completed Jun 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant