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

Function not implemented (os error 38) when running on docker in M1 MacOS #423

Open
samuelcolvin opened this issue Jul 20, 2022 · 10 comments
Labels
A-bug os-mac Z-needs implementation Needs an implementation, will accept PRs

Comments

@samuelcolvin
Copy link
Contributor

System details

See samuelcolvin/watchfiles#167 for initial report

What you did (as detailed as you can)

When running watchfiles, the following error occurs: Function not implemented (os error 38)

In watchfiles code, the error is caught and raised here.

This occurs when using RecommendedWatcher, when using PollWatcher everything seems to be fine.

There are a number of other similar reports of the same error message on other rust packages running in docker in the same way, see adamchainz/django-watchfiles#3. Those seem to related to missing binaries for MacOS M1, but watchfiles provides (AFAIK) all applicable binaries.

I think this is a problem with docker not providing the underlying functions which notify expects to find.

I think I can catch this error and fall back to PollWatcher in watchfiles but I wanted to report the issue here in case you had any insights or suggestions.

@samuelcolvin
Copy link
Contributor Author

A bit more detail on this:

As discovered by @messense, https://docs.docker.com/desktop/mac/apple-silicon/#known-issues

However, attempts to run Intel-based containers on Apple silicon machines under emulation can crash as qemu sometimes fails to run the container. In addition, filesystem change notification APIs (inotify) do not work under qemu emulation.

So I think notify should detect this and fallback to PollWatcher.

In case it helps, debug of the error is: { kind: Io(Os { code: 38, kind: Unsupported, message: "Function not implemented" }), paths: [] }.

I'm working round this in watchfiles, see samuelcolvin/watchfiles#172.

@0xpr03
Copy link
Member

0xpr03 commented Jul 20, 2022

I sadly can't test this at all, as I don't own an m1 device. And this can't be simulated by gh-actions?

Is there a specific conditional compilation architecture we could detect for this ? If possible I'd like to actively detect the feature instead of trying for error 38 first on macos.

@0xpr03 0xpr03 added this to the 5.0.0 milestone Jul 20, 2022
@samuelcolvin
Copy link
Contributor Author

Ye, I get the problem.

You won't be able to test on gh-actions or any other cloud service AFAIK.

I don't know of any to actively detect, but I guess there must be a way?

@messense
Copy link

messense commented Jul 21, 2022

Is there a specific conditional compilation architecture we could detect for this ?

I don't think there is. The target architecture is x86_64. You'd need to detect QEMU emulation at runtime, but that's not pretty either. https://stackoverflow.com/a/71643762

@0xpr03
Copy link
Member

0xpr03 commented Jul 21, 2022

So the question is: Do we want to add this error-code workaround into notify ?

The default-watcher is just an alias, so if you'd create an inotify watcher manually, you'd still have a chance of receiving a pollwatcher without any warning. I see this as bad behavior.

Ultimately the QEMU setup is lying to us..

@samuelcolvin
Copy link
Contributor Author

I hadn't quite appreciated the run-time vs. compile-time distinction at play here - that's my fault for thinking in python.

Do we want to add this error-code workaround into notify?

Well, I don't really have a dog in this fight anymore since it's fixed/worked-around in watchfiles.

My recommendation would be:

  • document the behaviour - kind of done by this issue
  • report it upstream to docker/QEMU if we can be bothered - I assume they already know and aren't that interested in fixing it, so I'm not sure of the point
  • move on

But ultimately, up to the maintainers of this package.

Feel free to close this issue.

@0xpr03
Copy link
Member

0xpr03 commented Jul 21, 2022

document the behaviour

Definitely.

I was thinking about a way to make the default-init able to catch such a case without inducing a ton of overhead. Currently the default watcher is selected at compile time.

@0xpr03
Copy link
Member

0xpr03 commented Aug 10, 2022

I'm adding a note about this in #395

A correct fix is a little bit more tricky.

@samuelcolvin
Copy link
Contributor Author

Looks good to me, thanks.

@0xpr03 0xpr03 added the Z-needs implementation Needs an implementation, will accept PRs label Aug 10, 2022
@samuelcolvin
Copy link
Contributor Author

For anyone else who comes to this issue here is the logic in watchfiles which catches this error and falls back to the poll watcher.

In particular, we catch this specific error with

                match RecommendedWatcher::new(event_handler.clone()) {
                    Ok(watcher) => {
                        ...
                    }
                    Err(error) => {
                        match &error.kind {
                            ErrorKind::Io(io_error) => {
                                if io_error.raw_os_error() == Some(38) {
                                    ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-bug os-mac Z-needs implementation Needs an implementation, will accept PRs
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants