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

Fix dup syscalls so that they handle pipes correctly #14808

Merged
merged 10 commits into from
Apr 4, 2022

Conversation

hoodmane
Copy link
Collaborator

@hoodmane hoodmane commented Aug 5, 2021

library_syscall duplicates things with var newStream = FS.open(stream.path, stream.flags, 0, arg); This doesn't work for pipes because in that case stream.path is e.g., pipe[1] and then FS.open raises an error because this is an invalid path.

I changed SYSCALL.doDup so that it no longer closes the target pipe because this logic makes sense for dup2 and dup3 but not for dup or fcntl F_DUPFD which don't close the target pipe. So now doDup takes a file stream and an inclusive range of file descriptors (like the last two arguments of createStream). Now doDup also checks if the stream is a pipe, in which case it increments the pipe refcount and uses createStream to duplicate the pipe.

@sbc100
Copy link
Collaborator

sbc100 commented Aug 13, 2021

How does this overlap with: #9396?

@hoodmane
Copy link
Collaborator Author

Looks to me like #9396 also solves this problem.

@hoodmane
Copy link
Collaborator Author

Would be good to at least add a test case for dup with a pipe though.

@hoodmane
Copy link
Collaborator Author

It would be nice to get a fix for this merged. I think when Pyodide is updated to use emscripten v3.1.6 the only remaining patch we will need is something to fix this problem.

@sbc100
Copy link
Collaborator

sbc100 commented Mar 21, 2022

Looks like a lot of dup related tests are failing.

This fixes two problems with the `dup` system calls:
1. `dup` expects that every file descriptor has a corresponding file (so pipes and (emscripten-core#14640)
   files that have been unlinked (emscripten-core#15012) cannot be duplicated ).
2. The dup'd file descriptor does not share flags and position with the original file desciptor.

This is a simplification of an upstream pull request that would fix this problem.
https://github.com/emscripten-core/emscripten/pull/9396/files
This patch is simpler than the upstream one but leaves NODERAWFS broken.
@hoodmane
Copy link
Collaborator Author

Maybe I fixed it?

I guess doDup is now only used in one place. I should probably add some test cases here. Maybe this could be better fixed by moving more of this stuff into syscalls.cpp or something but I'm not really sure how to do that.

@sbc100
Copy link
Collaborator

sbc100 commented Mar 22, 2022

I guess doDup is now only used in one place.

Good call... I guess we should just inline that function now. Do you want to send or PR for that? (if not I can do it).

@sbc100
Copy link
Collaborator

sbc100 commented Mar 22, 2022

Do you know how to run the failing tests to debug them? (See https://emscripten.org/docs/getting_started/test-suite.html)

@hoodmane
Copy link
Collaborator Author

Do you want to send or PR for that?

I can do it, in this PR or you want a different one?

sbc100 added a commit that referenced this pull request Mar 22, 2022
@sbc100
Copy link
Collaborator

sbc100 commented Mar 22, 2022

Do you want to send or PR for that?

I can do it, in this PR or you want a different one?

I think it would make sense as its own PR to land before this one

@hoodmane
Copy link
Collaborator Author

I'm trying to figure out even what isn't working on main. I'm getting test failures in Pyodide without this in test_dup_pipe, test_dup_temp_file and test_dup_stdout.

@sbc100
Copy link
Collaborator

sbc100 commented Mar 23, 2022

It could be that our tests just need to be updated. Some of the tests support WASMFS as well as the legacy filesystem (the thing you are changing in this PR). It could be that the failing tests have an '#ifdef WASMFS` in there, that could be removed?

@hoodmane
Copy link
Collaborator Author

hoodmane commented Mar 23, 2022

Okay here's an example of a test that would pick up the bug:

int main() {
  int p[2];
  pipe(p); 
  g = dup2(p[0], 7);
  write(p[1], "abc", 3);
  char buf[5];
  read(g, buf, 5);
  printf("buf: %s\n", buf); // should print "buf: abc\n" but it prints "buf: \n".
  return 0;
}

@hoodmane
Copy link
Collaborator Author

But it seems like there might be an additional bug now that's a regression since 2.0.16 because it does FS.open("pipe[0]", 0, 0, 7, 7) and that should return ENOENT but it doesn't.

@sbc100
Copy link
Collaborator

sbc100 commented Mar 23, 2022

I think the issue it not lack of testing of the bug but the breakage of existing tests by this change.

Adding to one of the existing tests would be nice too, but first they need to pass

@hoodmane
Copy link
Collaborator Author

I think I fixed the test failures though, can you trigger the CI?

@hoodmane
Copy link
Collaborator Author

Oh it's just waiting on build-linux.

@sbc100
Copy link
Collaborator

sbc100 commented Mar 23, 2022

I think I fixed the test failures though, can you trigger the CI?

Great... sorry i didn't understand that.

@hoodmane
Copy link
Collaborator Author

I think I fixed the test failures though

Guess not hmm. I must have made a mistake when I ran the tests locally...

@hoodmane
Copy link
Collaborator Author

Okay now it should work.

Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So all

@hoodmane
Copy link
Collaborator Author

@sbc100 Could you look into the current test failure? When I try to compile and run the the test_pthread_proxying_cpp test manually, it works fine. Not sure what this has to do with the changeset here...

@sbc100
Copy link
Collaborator

sbc100 commented Mar 27, 2022

I think its probably just a flake.. i restarted that test runner

@sbc100 sbc100 changed the title Fix duplication syscalls so that they handle pipes correctly Fix dup syscalls so that they handle pipes correctly Mar 27, 2022
@sbc100
Copy link
Collaborator

sbc100 commented Mar 29, 2022

I think this is looking good now. But I also think we do need to add some new testing. IIRC there might be some tests that are currently disabled .. taking a look.

@sbc100
Copy link
Collaborator

sbc100 commented Mar 29, 2022

It looks like we have two dup tests as of today:

  1. tests/unistd/dup.c
  2. tests/wasmfs/wasmfs_dup.c

Currently the later is a lot more extensive and only runs under WASMFS due to current limitations. Some of those limitations seem to have been addressed by this PR (its fails in fewer places with patch applies).

I think to land this PR we should add to the existing tests/unistd/dup.c, perhaps using the test from #14808 (comment).. and then as a followup perhaps look into the remaining reasons why tests/wasmfs/wasmfs_dup.c` doesn't work with the current FS.

@hoodmane
Copy link
Collaborator Author

Yeah good thing we added the test since the patch was still slightly wrong.

@hoodmane
Copy link
Collaborator Author

Perhaps could simplify the code by changed closeStream such that it takes the actual stream object and not the fd?

as a followup perhaps look into the remaining reasons why tests/wasmfs/wasmfs_dup.c doesn't work with the current FS

+1 for both of these.

@hoodmane
Copy link
Collaborator Author

hoodmane commented Apr 4, 2022

Does this need anything else? I think it's ready to merge?

@kripken
Copy link
Member

kripken commented Apr 4, 2022

Looks good to me, thanks, landing.

@kripken kripken merged commit a856e88 into emscripten-core:main Apr 4, 2022
@kripken
Copy link
Member

kripken commented Apr 5, 2022

It looks like this is causing errors on our roller,

https://logs.chromium.org/logs/emscripten-releases/buildbucket/cr-buildbucket/8817755857784351121/+/u/Emscripten_testsuite__upstream__cores_/stdout

Specifically test_unistd_truncate_noderawfs now fails,

-- expected
+++ actual
@@ -1,16 +1,17 @@
+f2: 4
 st_size: 6

-ftruncate(10): 0
-errno: No error information
-st_size: 10
+ftruncate(10): -1
+errno: Invalid argument
+st_size: 6

-ftruncate(4): 0
-errno: No error information
-st_size: 4
+ftruncate(4): -1
+errno: Invalid argument
+st_size: 6

 ftruncate(-1): -1
 errno: Invalid argument
-st_size: 4
+st_size: 6

 truncate(2): 0
 errno: No error information

I would guess the NODERAWFS changes here are causing that. It looks like we missed this on CI here because the test is skipped:

test_unistd_truncate_noderawfs (test_core.core3) ... skipped 'Root access invalidates this test by being able to write on readonly files'

That is, CI here runs as root I guess, while the chromium roller does not, so it can run an additional test, which failed.

Given that, I think you should be able to reproduce this locally in order to debug it @hoodmane ?

@hoodmane
Copy link
Collaborator Author

hoodmane commented Apr 5, 2022

Yup reproduces locally.

@hoodmane
Copy link
Collaborator Author

hoodmane commented Apr 5, 2022

Is there an easy way to make the test runner print out the compiler invocations it is using?

hoodmane added a commit to hoodmane/emscripten that referenced this pull request Apr 5, 2022
@kripken
Copy link
Member

kripken commented Apr 5, 2022

@hoodmane passing -v to tests/runner.py should do that I believe.

Doing EMCC_DEBUG=1 in the environment is another way to get full logging of each emcc command, including internals.

See also notes here for saving temp files https://emscripten.org/docs/getting_started/test-suite.html#debugging-test-failures

@hoodmane hoodmane deleted the fix-fcntl-dupfd branch April 5, 2022 18:26
kripken pushed a commit that referenced this pull request Apr 6, 2022
If the stream argument to fd.createStream already has an fd attribute, we don't want
to overwrite it. This was causing test_unistd_truncate_noderawfs to fail.
kleisauke added a commit to kleisauke/emscripten that referenced this pull request Apr 23, 2022
`refcnt` (and not `refcnf`) needs to be initialized by 1 when
creating the filestream.

Also, apply emscripten-core#16661 to the other `FS.createStream` invocations
as well.
kripken pushed a commit that referenced this pull request Apr 27, 2022
refcnt (and not refcnf) needs to be initialized by 1 when
creating the filestream.

Also, apply #16661 to the other FS.createStream invocations
as well.
sbc100 added a commit that referenced this pull request Apr 28, 2022
These arguments used to be used in `__syscall_pipe` and `__syscall_dup`
but were replaced with calls to createStream in #14808.
sbc100 added a commit that referenced this pull request Apr 29, 2022
These arguments used to be used in `__syscall_pipe` and `__syscall_dup`
but were replaced with calls to createStream in #14808.
@sbc100 sbc100 mentioned this pull request May 10, 2022
@hoodmane hoodmane mentioned this pull request Jun 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants