Skip to content

command: avoid crashing the player with mmap#17520

Open
N-R-K wants to merge 4 commits intompv-player:masterfrom
N-R-K:rm-mmap
Open

command: avoid crashing the player with mmap#17520
N-R-K wants to merge 4 commits intompv-player:masterfrom
N-R-K:rm-mmap

Conversation

@N-R-K
Copy link
Contributor

@N-R-K N-R-K commented Mar 7, 2026

mmap in inherently crashy due to the file changing underneath and requires esoteric SIGBUS handling 1 to use properly.

to reproduce, simply use "overlay-add" from a lua script with invalid stride set and observe mpv crashing with SIGBUS.

here we're just copying the file content and munmaping it immediately so there's no real need to be using mmap to begin with. just read the file directly with pread (with optimization for the common stride case) and avoid the issue entirely.

Footnotes

  1. https://www.sublimetext.com/blog/articles/use-mmap-with-care

@N-R-K N-R-K force-pushed the rm-mmap branch 2 times, most recently from 91b1f58 to 95e1e62 Compare March 7, 2026 21:10
@N-R-K N-R-K force-pushed the rm-mmap branch 2 times, most recently from 754163a to 3866a07 Compare March 8, 2026 00:08
@N-R-K
Copy link
Contributor Author

N-R-K commented Mar 8, 2026

What even was the point of accepting this weird fd argument when we accept memory address already?

549a9ea sort of implies wanting to deprecate the whole overlay-add command entirely, but there's actual scripts using this. Is there any actual script/client that's using this weird fd thing? We can consider deprecating it if not.

@na-na-hi
Copy link
Contributor

na-na-hi commented Mar 8, 2026

What even was the point of accepting this weird fd argument when we accept memory address already?

#255 (comment)

which why I made overlay_add also accept FDs (so mkstemp() could be used)

It also allows the overlay source and mpv to be separate processes without writing files to disk.

549a9ea sort of implies wanting to deprecate the whole overlay-add command entirely, but there's actual scripts using this.

osd-overlay is not a replacement because rendering bitmap images in ASS is very slow and cumbersome. There is currently no replacement for overlay-add.

@N-R-K N-R-K force-pushed the rm-mmap branch 4 times, most recently from b3939ce to 82b6e7c Compare March 8, 2026 01:12
player/command.c Outdated
bytesRead = fread(overlay.source->planes[0], 1, expectedBytes, fp);
} else for (int i = 0; i < h; i++) {
fseek(fp, src_off, SEEK_SET);
size_t r = fread(overlay.source->planes[0] + dst_off, 1, bytesPerLine, fp);
Copy link
Member

Choose a reason for hiding this comment

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

I think mmap was natural choice for this interface, as it not only simplifies the code, but reduces to syscalls bloat. Additionally in many cases only small ROI is copied from the source file.

Also theoretically you can mmap fd that is not seekable.

I understand mmap pitfals however, just pointing why it may have been desirable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also theoretically you can mmap fd that is not seekable.

mmap is only defined to work with regular files and shared/typed memory. And in practice stuff like pipe doesn't work with mmap so I doubt requiring the fd to be seekable is introducing some new constrain.

Copy link
Member

@kasper93 kasper93 Mar 9, 2026

Choose a reason for hiding this comment

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

If you assume only seekable fd is supported, you can use pread and ReadFile with OVERLAPPED structure to read data which you need, instead of seeking the file itself, which may be unexpected for the user.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This PR was initially doing pread except that windows doesn't have it.

ReadFile with OVERLAPPED structure

I did look into this, but it says:

For an hFile that does not support byte offsets, Offset and OffsetHigh are ignored.

This thing also seems to be tied to some async stuff? We obviously dont want the read to be async if the "fd" was async for some reason.

I am also a bit reluctant on doing windows stuff as I don't have an easy way to compile and test it locally. Making changes and pushing them to see if CI passes is a miserable state of affairs.

Copy link
Member

@kasper93 kasper93 Mar 9, 2026

Choose a reason for hiding this comment

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

For an hFile that does not support byte offsets, Offset and OffsetHigh are ignored.

Seeking is also required to be supported in current PR solution, so I see no difference.

This thing also seems to be tied to some async stuff?

Same as pread, it's an interface to allow multithreading, such that you don't modify global file state by seeking it, and allow multiple consumers to read different part of such file.

ReadFile itself is synchronous, there exist completelly async version with completion callback too (ReadFileEx).

I am also a bit reluctant on doing windows stuff as I don't have an easy way to compile and test it locally. Making changes and pushing them to see if CI passes is a miserable state of affairs.

That's life.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sfan5 had objection earlier to doing 1 syscall per line for the non-common case.

Is there any consensus on whether we should use pread and potentially take a performance hits on niche non-standard stride images or use buffered io and potentially risk breaking the api by seeking the fd.

I'm down (even if not enthusiastic) to try implement a pread windows shim but I want to know if that's the preferred method before I have to write windows code.

Copy link
Member

Choose a reason for hiding this comment

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

I would still prefer avoiding pread. Seeking in the fd isn't that much of a problem.
We could even restore the original file position.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could even restore the original file position.

It'd be racy though. If we're going to seek let's just do it and document it instead of pretending as if we didn't seek.

Copy link
Member

Choose a reason for hiding this comment

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

Sure. Just document that mpv may seek in the fd.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Already documented:

Note that since mpv 0.42.0, if a file descriptor is specified, the file
offset of the descriptor will be modified.

N-R-K added 2 commits March 9, 2026 15:41
_get_osfhandle returns INVALID_HANDLE_VALUE on failure, not 0.
N-R-K added 2 commits March 9, 2026 15:41
will be used in the next commit
mmap in inherently crashy due to the file changing underneath
and requires esoteric SIGBUS handling [0] to use properly.

to reproduce, simply use "overlay-add" from a lua script with
invalid stride set and observe mpv crashing with SIGBUS.

here we're just copying the file content (introduced in
549a9ea) and munmaping it immediately so there's no real need
to be using mmap to begin with. avoid the issue entirely by just
reading the file directly with fseek+fread with optimization for
the common stride case.

one notable difference is that since dup-ed fds share same
offset, the source "fd" that's coming from client will now have
it's offset modified. `pread` could avoid this issue but it's
not supported on windows.

[0]: https://www.sublimetext.com/blog/articles/use-mmap-with-care
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.

4 participants