You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SDL masks many signals, but this is expected: we do not want to receive SIGINT from other threads, and we want to always quit properly (for example, killing while recording could result in a corrupted file). And the solution must work on all platforms anyway.
Instead, to always quit properly, on Ctrl+c, SDL generates a SQL_QUIT event on the main thread, causing sc_server_stop() to be called, which in turn interrupts any blocking call on the server thread.
The problem is that even if the adb process (here, our bash script) is killed, the blocking read from the pipe is not interrupted (it is expected to return -1 immediately instead).
Even killing it from a separate terminal (during the sleep 10) does not help (the pipe read is still blocked), and the sleep is not even interrupted, which is very surprising.
However, if we use a native binary (instead of a shell script calling sleep) to simulate a blocking adb call:
In that case, it is interrupted immediately (as expected):
scrcpy 1.21 <https://github.com/Genymobile/scrcpy>
begin
DEBUG: Screensaver enabled
^CDEBUG: User requested to quit
DEBUG: Interrupting process
ERROR: Could not get device serial
A pipe read should return immediately when the other end is closed. So if it isn't, then the other end is not closed (probably due to a fork in the child process which keeps it open, and remains open even when the direct child process is killed).
I don't know how to fix it yet. Oh in fact this is also fixed by #2870.
A workaround could be to first wait for process success, then read the output pipe (in other words, reverse the calls here): the process is correctly interrupted on Ctrl+c, contrary to the pipe read. For such small output size, it works, but in the general case this is not correct: a process might be blocked if its stdout is full, causing a deadlock (the caller waits for the process to terminate before consuming its output, but the process is blocked on its output until it is consumed).
The text was updated successfully, but these errors were encountered:
Since commit 0426708, the server is run
in a dedicated thread. For SDL, many signals, including SIGINT and
SIGTERM, are masked for new threads. As a result, if the adb server is
not already running, adb commands invoked by scrcpy will start an adb
server that ignores those signals and cannot be terminated at system
shutdown.
Fixes#2873 <#2873>
PR #2870 <#2870>
Signed-off-by: Romain Vimont <[email protected]>
Environment
Related to #2870, interrupting an
adb get-serialno
process with Ctrl+c does not close scrcpy immediately in all situations.To reproduce easily, create an adb wrapper (called
slowadb
for this example), and make it executable (chmod +x slowadb
):Then use it for scrcpy:
export ADB=./slowadb scrcpy
Pressing Ctrl+c does not interrupt it.
Analysis
SDL masks many signals, but this is expected: we do not want to receive SIGINT from other threads, and we want to always quit properly (for example, killing while recording could result in a corrupted file). And the solution must work on all platforms anyway.
Instead, to always quit properly, on Ctrl+c, SDL generates a
SQL_QUIT
event on the main thread, causingsc_server_stop()
to be called, which in turn interrupts any blocking call on the server thread.The problem is that even if the
adb
process (here, our bash script) is killed, the blocking read from the pipe is not interrupted (it is expected to return -1 immediately instead).Even killing it from a separate terminal (during the
sleep 10
) does not help (the pipe read is still blocked), and thesleep
is not even interrupted, which is very surprising.However, if we use a native binary (instead of a shell script calling
sleep
) to simulate a blocking adb call:gcc a.c export ADB=./a.out scrcpy
In that case, it is interrupted immediately (as expected):
A pipe read should return immediately when the other end is closed. So if it isn't, then the other end is not closed (probably due to a fork in the child process which keeps it open, and remains open even when the direct child process is killed).
I don't know how to fix it yet.Oh in fact this is also fixed by #2870.A workaround could be to first wait for process success, then read the output pipe (in other words, reverse the calls here): the process is correctly interrupted on Ctrl+c, contrary to the pipe read. For such small output size, it works, but in the general case this is not correct: a process might be blocked if its stdout is full, causing a deadlock (the caller waits for the process to terminate before consuming its output, but the process is blocked on its output until it is consumed).
The text was updated successfully, but these errors were encountered: