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

Missing mock of os.dup #970

Closed
vector-of-bool opened this issue Mar 11, 2024 · 4 comments · Fixed by #985
Closed

Missing mock of os.dup #970

vector-of-bool opened this issue Mar 11, 2024 · 4 comments · Fixed by #985
Labels

Comments

@vector-of-bool
Copy link

Describe the bug
The os.dup function is not implemented by pyfakefs, and defers to the underlying dup. This can cause the pyfakefs file numbers to be given to the real dup syscall, leading to unexpected behavior.

How To Reproduce

def read_with_dup(s: Path):
    s.write_text("heythere")
    fd1 = os.open(s, os.O_RDONLY)
    fd2 = os.dup(fd1)
    dat1 = os.read(fd1, 3)
    dat2 = os.read(fd2, 10)
    os.close(fd1)
    os.close(fd2)
    assert dat1 == b"hey"
    assert dat2 == b"there"

def test_realfs():
    read_with_dup(Path("file.txt"))

def test_fakefs(fs):
    read_with_dup(Path("file.txt"))

The fileno returned by the patched os.open will be given to the built-in os.dup, which may or may not generate an error depending on whether fd1 is coincidentally equal to a real file descriptor. The call to os.read(fd2) will likely fail since the patched os.read will be given a fileno that wasn't created by pyfakefs.

Your environment
Please run the following in the environment where the problem happened and
paste the output.

$ python -c "import platform; print(platform.platform())"
Linux-6.7.6-arch1-1-x86_64-with-glibc2.39
$ python -c "import sys; print('Python', sys.version)"
Python 3.11.7 (main, Jan 29 2024, 16:03:57) [GCC 13.2.1 20230801]
$ python -c "from pyfakefs import __version__; print('pyfakefs', __version__)"
pyfakefs 5.4.dev0
$ python -c "import pytest; print('pytest', pytest.__version__)"
pytest 7.2.0

This one may be trickier to solve since os.dup is also useful with non-filesystem file descriptors. i.e. it would be bad if pyfakefs broke os.dup for sockets and pipes. Distinguishing between a socket fileno and a fakefs fileno may require separating the domain of integers used by the fake os module.

@mrbean-bremen
Copy link
Member

I remember having done something about that some time ago, but obviously didn't finish it...
Thanks for the daily issue 😀

@mrbean-bremen
Copy link
Member

This one may be trickier to solve since os.dup is also useful with non-filesystem file descriptors. i.e. it would be bad if pyfakefs broke os.dup for sockets and pipes.

Hm, that would also be true for open and other calls. We currently only handle files (by faking them) and pipes (by pointing a fake descriptor to a real one). Both should also work for a fake dup.
I don't think that we support sockets at all. This never came up, probably because applications using sockets will usually not be used with pyfakefs, and I will probably just ignore that as long as it does not come in a real use case.

mrbean-bremen added a commit to mrbean-bremen/pyfakefs that referenced this issue Mar 16, 2024
mrbean-bremen added a commit to mrbean-bremen/pyfakefs that referenced this issue Mar 16, 2024
@mrbean-bremen
Copy link
Member

@vector-of-bool - this was the last of your issues so far. I will wait with a release at least until you have retested with the current version.

@vector-of-bool
Copy link
Author

Thanks! I'll test things out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants