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

V1.20 version can only open one device window when multiple devices are connected. #2779

Closed
Helaer opened this issue Nov 14, 2021 · 26 comments
Closed

Comments

@Helaer
Copy link

Helaer commented Nov 14, 2021

V1.20 version can only open one device window when multiple devices are connected, and the computer system is windows10.

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

V1.20 version can only open one device window when multiple devices are connected, and the computer system is windows10.

The startup command is: scrcpy -s serial number.

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Could not reproduce.

Could you please copy-paste the exact command you execute and the whole console output?

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

Could not reproduce.

Could you please copy-paste the exact command you execute and the whole console output?

First device
D:\scrcpy-win64-v1.20>adb devices
List of devices attached
66J5T19614020092 device
e2b16c device

D:\scrcpy-win64-v1.20>scrcpy -s 66J5T19614020092
INFO: scrcpy 1.20 https://github.com/Genymobile/scrcpy
D:\scrcpy-win64-v1.20\scrcpy-server: 1 file pushed, 0 skipped. 15.7 MB/s (37139 bytes in 0.002s)
[server] INFO: Device: HUAWEI HMA-AL00 (Android 10)
INFO: Renderer: direct3d
INFO: Initial texture: 1080x2240

Second device
D:\scrcpy-win64-v1.20>adb devices
List of devices attached
66J5T19614020092 device
e2b16c device

D:\scrcpy-win64-v1.20>scrcpy -s e2b16c
INFO: scrcpy 1.20 https://github.com/Genymobile/scrcpy
D:\scrcpy-win64-v1.20\scrcpy-server: 1 file pushed, 0 skipped. 39.1 MB/s (37139 bytes in 0.001s)
[server] INFO: Device: Xiaomi M2007J3SC (Android 11)

The second device cannot display the projection window, and the device will light up.

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Does it work if there is only one device connected?

Does the second device work with scrcpy v1.19?

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

Does it work if there is only one device connected?

Does the second device work with scrcpy v1.19?

V1.19 includes the previous version and everything is normal. You can also test multiple devices on windows.

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

Does it work if there is only one device connected?

Does the second device work with scrcpy v1.19?

It is found that regardless of whether it is multiple devices or the same device, only one window can be opened in the V1.20 version, and the V1.19 version does not have this problem.

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

It seems you are not alone having this kind of problem with a secondary scrcpy instance with v1.20: #2778 (comment)

However, I fail to reproduce. Is it over USB or wifi?

Could you try opening two instances for a device connected via wifi?

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

使用 v1.20 的辅助 scrcpy 实例似乎并非只有您一个人遇到这种问题:#2778(评论)

但是,我无法重现。是通过USB还是wifi?

您可以尝试为通过 wifi 连接的设备打开两个实例吗?

使用 v1.20 的辅助 scrcpy 实例似乎并非只有您一个人遇到这种问题:#2778(评论)

但是,我无法重现。是通过USB还是wifi?

您可以尝试为通过 wifi 连接的设备打开两个实例吗?

It seems you are not alone having this kind of problem with a secondary scrcpy instance with v1.20: #2778 (comment)

However, I fail to reproduce. Is it over USB or wifi?

Could you try opening two instances for a device connected via wifi?

I did not use VBS to start, but directly entered scrcpy -s in the console to specify the device to start. Whether it is wired, wireless, multiple device connection, or single device connection, I can always start only one scrcpy window, and start the other will be stuck. The corresponding window will not appear. In V1.19 and earlier versions, multiple device windows can be opened at the same time.

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Hmm… I really fail to reproduce, either with one device opened twice, or two devices open once, I can always open multiple scrcpy window instances with v1.20.

I will continue to try to reproduce, but if you get any additional info, please share :)

(You run the two instances of scrcpy from two separate terminals, correct?)

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

嗯……我真的无法重现,无论是一个设备打开两次,还是两个设备打开一次,我总是可以用v1.20打开多个scrcpy窗口实例。

我将继续尝试重现,但如果您获得任何其他信息,请分享:)

(您从两个不同的终端运行两个 scrcpy 实例,对吗?)

Yes, I run it from two different terminals.

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

嗯……我真的无法重现,无论是一个设备打开两次,还是两个设备打开一次,我总是可以用v1.20打开多个scrcpy窗口实例。

我将继续尝试重现,但如果您获得任何其他信息,请分享:)

(您从两个不同的终端运行两个 scrcpy 实例,对吗?)

Start a device in a terminal, and then open a terminal to start other devices. The first device to start can open the window normally, and the other consoles will be stuck and no error message is generated.

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Start a device in a terminal, and then open a terminal to start other devices.

I just did exactly this, and both device windows are correctly open.

Could you run with scrcpy -Vdebug, there might be more information.

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

Start a device in a terminal, and then open a terminal to start other devices.

I just did exactly this, and both device windows are correctly open.

Could you run with scrcpy -Vdebug, there might be more information.

After one terminal is started, the other terminal will only display these.

D:\scrcpy-win64-v1.20>scrcpy -s 66J5T19614020092 -Vdebug
INFO: scrcpy 1.20 https://github.com/Genymobile/scrcpy
DEBUG: Using server (portable): D:\scrcpy-win64-v1.20\scrcpy-server
DEBUG: Screensaver enabled
D:\scrcpy-win64-v1.20\scrcpy-server: 1 file pushed, 0 skipped. 74.1 MB/s (37139 bytes in 0.000s)
[server] INFO: Device: HUAWEI HMA-AL00 (Android 10)
[server] DEBUG: Using encoder: 'OMX.hisi.video.encoder.avc'
[server] DEBUG: Controller stopped

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

在终端中启动设备,然后打开终端启动其他设备。

我就是这样做的,两个设备窗口都正确打开。

你能用 运行吗scrcpy -Vdebug,可能会有更多信息。

The terminal that starts normally is displayed like this.

D:\scrcpy-win64-v1.20>scrcpy -s e2b16c -Vdebug
INFO: scrcpy 1.20 <https://github.com/Genymobile/scrcpy>
DEBUG: Using server (portable): D:\scrcpy-win64-v1.20\scrcpy-server
DEBUG: Screensaver enabled
D:\scrcpy-win64-v1.20\scrcpy-server: 1 file pushed, 0 skipped. 75.9 MB/s (37139 bytes in 0.000s)
[server] INFO: Device: Xiaomi M2007J3SC (Android 11)
[server] DEBUG: Using encoder: 'OMX.qcom.video.encoder.avc'
DEBUG: Server connected
DEBUG: Starting controller thread
DEBUG: Starting receiver thread
INFO: Renderer: direct3d
DEBUG: Trilinear filtering disabled (not an OpenGL renderer)
DEBUG: Using icon (portable): D:\安卓投屏源码\scrcpy-win64-v1.20\icon.png
INFO: Initial texture: 1080x2400
DEBUG: Starting stream thread

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

[server] DEBUG: Controller stopped

Oh, interesting.

When this happens, is there something interesting in adb logcat?

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

OK, let's try to add more logs:

diff
diff --git a/app/src/adb_tunnel.c b/app/src/adb_tunnel.c
index f02eb83e..d5f635f0 100644
--- a/app/src/adb_tunnel.c
+++ b/app/src/adb_tunnel.c
@@ -25,6 +25,7 @@ disable_tunnel_reverse(struct sc_intr *intr, const char *serial) {
 static bool
 enable_tunnel_forward(struct sc_intr *intr, const char *serial,
                       uint16_t local_port) {
+    LOGI("=== adb forward: %s %d", serial, (int) local_port);
     sc_pid pid = adb_forward(serial, local_port, SC_SOCKET_NAME);
     return sc_process_check_success_intr(intr, pid, "adb forward");
 }
@@ -32,6 +33,7 @@ enable_tunnel_forward(struct sc_intr *intr, const char *serial,
 static bool
 disable_tunnel_forward(struct sc_intr *intr, const char *serial,
                        uint16_t local_port) {
+    LOGI("=== adb forward remove: %s %d", serial, (int) local_port);
     sc_pid pid = adb_forward_remove(serial, local_port);
     return sc_process_check_success_intr(intr, pid, "adb forward --remove");
 }
diff --git a/app/src/server.c b/app/src/server.c
index d792364d..e89b1865 100644
--- a/app/src/server.c
+++ b/app/src/server.c
@@ -342,43 +342,72 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
     sc_socket video_socket = SC_SOCKET_NONE;
     sc_socket control_socket = SC_SOCKET_NONE;
     if (!tunnel->forward) {
+        LOGD("=== Tunnel reverse");
+
+        LOGD("=== video_socket accept()");
         video_socket = net_accept_intr(&server->intr, tunnel->server_socket);
         if (video_socket == SC_SOCKET_NONE) {
+            LOGD(" --> video_socket ko");
             goto fail;
         }
+        LOGD(" --> video_socket ok");
 
+        LOGD("=== control_socket accept()");
         control_socket = net_accept_intr(&server->intr, tunnel->server_socket);
         if (control_socket == SC_SOCKET_NONE) {
+            LOGD(" --> control_socket ko");
             goto fail;
         }
+        LOGD(" --> control_socket ok");
     } else {
+        LOGD("=== Tunnel forward");
+
         uint32_t attempts = 100;
         sc_tick delay = SC_TICK_FROM_MS(100);
+        LOGD("=== video_socket connect_to_server()");
         video_socket = connect_to_server(server, attempts, delay);
         if (video_socket == SC_SOCKET_NONE) {
+            LOGD(" --> video_socket ko");
             goto fail;
         }
+        LOGD(" --> video_socket ok");
 
         // we know that the device is listening, we don't need several attempts
         control_socket = net_socket();
         if (control_socket == SC_SOCKET_NONE) {
+            LOGD("  control_socket net_socket() failed");
             goto fail;
         }
+        LOGD("=== control_socket connect()");
         bool ok = net_connect_intr(&server->intr, control_socket,
                                    IPV4_LOCALHOST, tunnel->local_port);
         if (!ok) {
+            LOGD(" --> control_socket ko");
             goto fail;
         }
+        LOGD(" --> control_socket ok");
     }
 
+    LOGD("=== Close adb tunnel");
     // we don't need the adb tunnel anymore
     sc_adb_tunnel_close(tunnel, &server->intr, serial);
 
     // The sockets will be closed on stop if device_read_info() fails
+    LOGD("=== Device read info");
     bool ok = device_read_info(&server->intr, video_socket, info);
     if (!ok) {
+        LOGD("  --> device read info ko");
         goto fail;
     }
+    LOGD("  --> device info: [%s] %ux%u", info->device_name,
+         info->frame_size.width, info->frame_size.height);
+
+    if (video_socket == SC_SOCKET_NONE) {
+        LOGD("video_socket not initialized");
+    }
+    if (control_socket == SC_SOCKET_NONE) {
+        LOGD("control_socket not initialized");
+    }
 
     assert(video_socket != SC_SOCKET_NONE);
     assert(control_socket != SC_SOCKET_NONE);
@@ -389,6 +418,7 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
     return true;
 
 fail:
+    LOGD("  server_connect_to goto fail");
     if (video_socket != SC_SOCKET_NONE) {
         if (!net_close(video_socket)) {
             LOGW("Could not close video socket");
@@ -439,6 +469,10 @@ run_server(void *data) {
         goto error_connection_failed;
     }
 
+    LOGD("tunnel %s %" PRIu16 "\n", server->tunnel.forward ? "forward"
+                                                           : "reverse",
+                                    server->tunnel.local_port);
+
     // server will connect to our server socket
     sc_pid pid = execute_server(server, params);
     if (pid == SC_PROCESS_NONE) {
diff --git a/app/src/util/intr.c b/app/src/util/intr.c
index 50d9abbe..5f41acd5 100644
--- a/app/src/util/intr.c
+++ b/app/src/util/intr.c
@@ -54,6 +54,7 @@ void
 sc_intr_interrupt(struct sc_intr *intr) {
     sc_mutex_lock(&intr->mutex);
 
+    LOGD("Interrupt");
     atomic_store_explicit(&intr->interrupted, true, memory_order_relaxed);
 
     // No more than one component to interrupt
diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java
index fdd9db88..db883416 100644
--- a/server/src/main/java/com/genymobile/scrcpy/Server.java
+++ b/server/src/main/java/com/genymobile/scrcpy/Server.java
@@ -99,6 +99,7 @@ public final class Server {
                 try {
                     controller.control();
                 } catch (IOException e) {
+                    e.printStackTrace();
                     // this is expected on close
                     Ln.d("Controller stopped");
                 }
@@ -115,6 +116,7 @@ public final class Server {
                 try {
                     sender.loop();
                 } catch (IOException | InterruptedException e) {
+                    e.printStackTrace();
                     // this is expected on close
                     Ln.d("Device message sender stopped");
                 }

Replace these binaries in your v1.20 release:

  • scrcpy.exe sha256:5e18bb92871ff6b235ad5fbe9387c96161bc187fe035e77c9756eaaf9de35a25
  • scrcpy-server sha256:4415572dceefeee7b82c78027374cccab804440e7e3ac0fd5e4d1892dba6d507

Then reproduce the issue, and post:

  1. the console output of the first scrcpy -Vdebug (which works)
  2. the console output of the second scrcpy -Vdebug (which does not work)
  3. post the adb logcat output (run adb logcat -c to clean before running scrcpy, then adb logcat -d > logs.txt to capture the logs after scrcpy is closed)

@Helaer
Copy link
Author

Helaer commented Nov 14, 2021

好的,让我们尝试添加更多日志:

差异
在 v1.20 版本中替换这些二进制文件:

  • scrcpy.exe sha256:5e18bb92871ff6b235ad5fbe9387c96161bc187fe035e77c9756eaaf9de35a25
  • scrcpy-server sha256:4415572dceefeee7b82c78027374cccab804440e7e3ac0fd5e4d1892dba6d507

然后重现问题,并发布:

  1. 第一个scrcpy -Vdebug(有效)的控制台输出
  2. 第二个的控制台输出scrcpy -Vdebug(不起作用)
  3. 发布 adb logcat 输出(adb logcat -c在运行 scrcpy 之前运行清洁,然后adb logcat -d > logs.txt在 scrcpy 关闭后捕获日志)

Console output
D:\scrcpy-win64-v1.20>scrcpy -s 66J5T19614020092 -Vdebug
INFO: scrcpy 1.20 https://github.com/Genymobile/scrcpy
DEBUG: Using server (portable): D:\scrcpy-win64-v1.20\scrcpy-server
DEBUG: Screensaver enabled
D:\scrcpy-win64-v1.20\scrcpy-server: 1 file pushed, 0 skipped. 56.8 MB/s (37191 bytes in 0.001s)
DEBUG: tunnel reverse 27183
DEBUG: === Tunnel reverse
DEBUG: === video_socket accept()
[server] INFO: Device: HUAWEI HMA-AL00 (Android 10)
[server] DEBUG: Using encoder: 'OMX.hisi.video.encoder.avc'
[server] DEBUG: Controller stopped
java.io.EOFException: Controller socket closed
at com.genymobile.scrcpy.ControlMessageReader.readFrom(ControlMessageReader.java:43)
at com.genymobile.scrcpy.DesktopConnection.receiveControlMessage(DesktopConnection.java:109)
at com.genymobile.scrcpy.Controller.handleEvent(Controller.java:80)
at com.genymobile.scrcpy.Controller.control(Controller.java:71)
at com.genymobile.scrcpy.Server$2.run(Server.java:100)
at java.lang.Thread.run(Thread.java:929)
DEBUG: User requested to quit
DEBUG: Interrupt
DEBUG: Interrupting socket
DEBUG: Interrupt
DEBUG: Server disconnected
DEBUG: --> video_socket ko
DEBUG: Server terminated
DEBUG: server_connect_to goto fail

adb log
logs.txt

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Thank you.

Could you also post the console output of the first scrcpy (which works)?

Could you please also do the same test with --force-adb-forward? (just post the console output of both cases, but not the adb logcat)

@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Oh it seems it happens only with adb reverse. I can reproduce now. Thank you. I will investigate.

rom1v added a commit that referenced this issue Nov 14, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

One possibility could be to use an extended API to set extra attributes
on process creation:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>
But it seems that this API is not available on MinGW (it does not
compile).

As an alternative, explicitly mark all sockets as non-inheritable.

Fixes #2779 <#2779>
rom1v added a commit that referenced this issue Nov 14, 2021
rom1v added a commit that referenced this issue Nov 14, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

One possibility could be to use an extended API to set extra attributes
on process creation:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

But it seems that this API is not available on MinGW (it does not
compile).

As an alternative, explicitly mark all sockets as non-inheritable.

Fixes #2779 <#2779>
rom1v added a commit that referenced this issue Nov 14, 2021
rom1v added a commit that referenced this issue Nov 14, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

As a result, the server socket is inherited by the process running adb
to execute the server on the device, so it may not be closed properly,
causing other instances of scrcpy to fail.

To fix the issue, use an extended API to explicitly set the HANDLE to
inherit:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

Fixes #2779 <#2779>
@rom1v
Copy link
Collaborator

rom1v commented Nov 14, 2021

Please test #2783.

rom1v added a commit that referenced this issue Nov 14, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

As a result, the server socket is inherited by the process running adb
to execute the server on the device, so it may not be closed properly,
causing other scrcpy instances to fail.

To fix the issue, use an extended API to explicitly set the HANDLE to
inherit:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

Fixes #2779 <#2779>
rom1v added a commit that referenced this issue Nov 14, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

As a result, the server socket is inherited by the process running adb
to execute the server on the device, so it may not be closed properly,
causing other scrcpy instances to fail.

To fix the issue, use an extended API to explicitly set the HANDLE to
inherit:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

Fixes #2779 <#2779>
@Helaer
Copy link
Author

Helaer commented Nov 15, 2021

哦,它似乎只发生在adb reverse. 我现在可以繁殖了。谢谢你。我会调查。

It can work normally, thank you!

rom1v added a commit that referenced this issue Nov 15, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

As a result, the server socket is inherited by the process running adb
to execute the server on the device, so it may not be closed properly,
causing other scrcpy instances to fail.

To fix the issue, use an extended API to explicitly set the HANDLE to
inherit:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

Fixes #2779 <#2779>
@rom1v
Copy link
Collaborator

rom1v commented Nov 15, 2021

@Helaer I just pushed a"final" version (hopefully) of the fix in #2783. I provide new binaries on that PR.

Could you please test them and confirm everything works as expected for you?

I think I will publish a new hotfix release (1.20.1) for this bug soon.

@Helaer
Copy link
Author

Helaer commented Nov 15, 2021

@Helaer I just pushed a"final" version (hopefully) of the fix in #2783. I provide new binaries on that PR.

Could you please test them and confirm everything works as expected for you?

I think I will publish a new hotfix release (1.20.1) for this bug soon.

I tested it with 2783, no problem。

@rom1v
Copy link
Collaborator

rom1v commented Nov 15, 2021

@Helaer Thank you 👍 (just to be sure, you tested with the latest binaries I updated just before I posted the comment 15 minutes ago, not the previous ones)

rom1v added a commit that referenced this issue Nov 15, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

As a result, the server socket was inherited by the process running adb
to execute the server on the device, so it could not be closed properly,
causing other scrcpy instances to fail.

To fix the issue, use an extended API to explicitly set the HANDLEs to
inherit:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

Fixes #2779 <#2779>
@Helaer
Copy link
Author

Helaer commented Nov 15, 2021

@Helaer Thank you 👍 (just to be sure, you tested with the latest binaries I updated just before I posted the comment 15 minutes ago, not the previous ones)

I just re-downloaded the #2783 test and everything is normal.

rom1v added a commit that referenced this issue Nov 15, 2021
To be able to communicate with a child process via stdin, stdout and
stderr, the CreateProcess() parameter bInheritHandles must be set to
TRUE. But this causes *all* handles to be inherited, including sockets.

As a result, the server socket was inherited by the process running adb
to execute the server on the device, so it could not be closed properly,
causing other scrcpy instances to fail.

To fix the issue, use an extended API to explicitly set the HANDLEs to
inherit:
 - <https://stackoverflow.com/a/28185363/1987178>
 - <https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873>

Fixes #2779 <#2779>
PR #2783 <#2783>
@rom1v
Copy link
Collaborator

rom1v commented Nov 15, 2021

Thanks! Fixed by #2783 then, I'm closing.

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 a pull request may close this issue.

2 participants