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

High CPU usage when running in disowned mode #11795

Closed
nightfriendly opened this issue Jun 16, 2023 · 6 comments · Fixed by #11871
Closed

High CPU usage when running in disowned mode #11795

nightfriendly opened this issue Jun 16, 2023 · 6 comments · Fixed by #11871

Comments

@nightfriendly
Copy link

nightfriendly commented Jun 16, 2023

Important Information

  • mpv version
[cplayer] mpv 0.35.1 Copyright © 2000-2023 mpv/MPlayer/mplayer2 projects
[cplayer]  built on Thu Feb  9 22:33:08 CET 2023
[cplayer] FFmpeg library versions:
[cplayer]    libavutil       57.28.100
[cplayer]    libavcodec      59.37.100
[cplayer]    libavformat     59.27.100
[cplayer]    libswscale      6.7.100
[cplayer]    libavfilter     8.44.100
[cplayer]    libswresample   4.7.100
[cplayer] FFmpeg version: 5.1.2
  • macOS Version: Ventura 13.4, MacBook Air M2
  • Source of the mpv binary or bundle: https://laboratory.stolendata.net/~djinn/mpv_osx/
  • If known which version of mpv introduced the problem: problem observed with 0.30.0, 0.34.1.
  • Possible screenshot or video of visual glitches: not relevant

Reproduction steps

# Start mpv in zsh' disowned mode
$ ./mpv --no-config *.mkv &!
# CPU is around 30%
$ exit

After exiting the terminal, Activity Monitor reports CPU 110%, Preventing Sleep Yes.

Expected behavior

Closing the terminal that ran mpv should have no impact on the CPU usage, even when paused.

Actual behavior

CPU is above 100%.

Log file

output.txt. Made with -v -v --log-file=output.txt.

This doesn't seem related to #11667.

@low-batt
Copy link
Contributor

Reproduced for me with a build from master.

The terminal thread is calling read which is failing and returning the errro code EIO (5). The code retries unless EBADF or EINVAL is returned:

mpv/osdep/terminal-unix.c

Lines 422 to 424 in 650c53d

int retval = read(tty_in, &buf.b[buf.len], BUF_LEN - buf.len);
if (!retval || (retval == -1 && (errno == EBADF || errno == EINVAL)))
break; // EOF/closed

So the terminal thread is in a tight loop retrying the read call.

@nightfriendly
Copy link
Author

Thank you so much for looking into this! So it means:

if (!retval || (retval == -1 && (errno == EBADF || errno == EINVAL)))

Should be changed to:

 if (!retval || (retval == -1 && (errno == EBADF || errno == EINVAL || errno == EIO)))

@low-batt
Copy link
Contributor

Maybe. Maybe not. I did confirm that as expected making such a change corrects the CPU usage in the case at hand. One worry is that EIO is a rather generic error that may be returned under other circumstances. Before considering such a fix the issue and change that introduced this code should be reviewed to see if there is a better way to address that issue.

Given that, I did not propose a fix as I thought it best this be handled by developers familiar with the history of problems with this source.

@nightfriendly
Copy link
Author

nightfriendly commented Jun 18, 2023

The original logic was introduced in 4b5c3ea#diff-5430e3916d2be16faed7c318993e5f26cefae4a686da8f699af4c67814dbf68eR194 and later modified in 6023843#diff-5430e3916d2be16faed7c318993e5f26cefae4a686da8f699af4c67814dbf68eR405 to fix #5833.

The author of both commits, wm4, does not seem to be around anymore.

man 2 read on MacOS tells us it returns EIO in these cases:

     [EIO]              An I/O error occurred while reading from the file system.

     [EIO]              The process group is orphaned.

     [EIO]              The file is a regular file, nbyte is greater than 0, the starting position is before
                        the end-of-file, and the starting position is greater than or equal to the offset
                        maximum established for the open file descriptor associated with fildes.

On Linux:

EIO           I/O error.  This will happen for example when the process
              is in a background process group, tries to read from its
              controlling terminal, and either it is ignoring or
              blocking SIGTTIN or its process group is orphaned.  It may
              also occur when there is a low-level I/O error while
              reading from a disk or tape.  A further possible cause of
              EIO on networked filesystems is when an advisory lock had
              been taken out on the file descriptor and this lock has
              been lost.  See the Lost locks section of fcntl(2) for
              further details.

It seems therefore pretty normal to stop trying and break out of the loop.

@Akemi, sorry to ping you directly, but we might need your guidance here. If you agree with the proposed solution above, I can prepare a pull request.

@Akemi
Copy link
Member

Akemi commented Jun 18, 2023

for me this would seem fine at first glance. though this change doesn't only affect macOS but linux too and i am not too familiar with this part of the code.

i think it's best to open a PR and let someone with more linux experience look over it too.

@Akemi Akemi added the os:linux label Jun 18, 2023
nightfriendly pushed a commit to nightfriendly/mpv that referenced this issue Jun 18, 2023
This commit fixes mpv-player#11795.

If parent terminal is closed while mpv is running, read(2) starts
returning EIO, resulting in an infinite loop using 100% of the CPU.

This commit makes sure we don't loop needlessly if read(2) returns EIO.
nightfriendly pushed a commit to nightfriendly/mpv that referenced this issue Jun 18, 2023
This commit fixes mpv-player#11795.

If parent terminal is closed while mpv is running, read(2) starts
returning EIO, resulting in an infinite loop using 100% of the CPU.

This commit makes sure we don't loop needlessly if read(2) returns EIO.
nightfriendly pushed a commit to nightfriendly/mpv that referenced this issue Jun 18, 2023
This commit fixes mpv-player#11795.

If parent terminal is closed while mpv is running, read(2) starts
returning EIO, resulting in an infinite loop using 100% of the CPU.

This commit makes sure we don't loop needlessly if read(2) returns EIO.
N-R-K added a commit to N-R-K/mpv that referenced this issue Jul 1, 2023
the reason for checking `EBADF|EINVAL` specifically is unknown. but it's
clearly not working as intended since it can cause issues like mpv-player#11795.

instead of checking for "bad errors" check for known "good errors" where
we might not want to break out. this includes:

* EINTR: which can happen if read() is interrupted by some signal.
* EAGAIN: which happens if a non-blocking fd would block. `tty_in` is
  _not_ non-blocking, so EAGAIN should never occur here. but it's added
  just in case that changes in the future.

Fixes: mpv-player#11795
Closes: mpv-player#11805
sfan5 pushed a commit that referenced this issue Jul 8, 2023
the reason for checking `EBADF|EINVAL` specifically is unknown. but it's
clearly not working as intended since it can cause issues like #11795.

instead of checking for "bad errors" check for known "good errors" where
we might not want to break out. this includes:

* EINTR: which can happen if read() is interrupted by some signal.
* EAGAIN: which happens if a non-blocking fd would block. `tty_in` is
  _not_ non-blocking, so EAGAIN should never occur here. but it's added
  just in case that changes in the future.

Fixes: #11795
Closes: #11805
N-R-K added a commit to N-R-K/mpv that referenced this issue Jul 20, 2023
fixes regression caused by 2e7fcc5 where it wouldn't receive terminal
input if the process was foregrounded later on like this:

    $ mpv something.mp4 &
    $ fg

ref: mpv-player#11795
@N-R-K
Copy link
Contributor

N-R-K commented Jul 20, 2023

Looks like breaking on EIO wasn't a good idea since it breaks terminal input when mpv is foregrounded later on (reported by @guidocella on IRC).

I've added a different fix in #11975 to deal with that. It would be nice if someone on mac can test it out and confirm everything still works fine.

sfan5 pushed a commit that referenced this issue Jul 21, 2023
fixes regression caused by 2e7fcc5 where it wouldn't receive terminal
input if the process was foregrounded later on like this:

    $ mpv something.mp4 &
    $ fg

ref: #11795
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants