mirror of
https://github.com/Genymobile/scrcpy.git
synced 2024-09-12 05:21:18 +02:00
Do not report error on device disconnected
A device disconnection (when the adb connection is closed) makes the
read() on the "receiver" socket fail.
Since commit 063a8339ed
, this is reported
as an error. As a consequence, scrcpy fails with:
ERROR: Controller error
instead of:
WARN: Device disconnected
To fix the issue, report a device disconnection in that case.
PR #5044 <https://github.com/Genymobile/scrcpy/pull/5044>
This commit is contained in:
parent
a4f8c02502
commit
b419eef55e
5 changed files with 43 additions and 21 deletions
|
@ -7,12 +7,13 @@
|
||||||
#define SC_CONTROL_MSG_QUEUE_MAX 64
|
#define SC_CONTROL_MSG_QUEUE_MAX 64
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_controller_receiver_on_error(struct sc_receiver *receiver, void *userdata) {
|
sc_controller_receiver_on_ended(struct sc_receiver *receiver, bool error,
|
||||||
|
void *userdata) {
|
||||||
(void) receiver;
|
(void) receiver;
|
||||||
|
|
||||||
struct sc_controller *controller = userdata;
|
struct sc_controller *controller = userdata;
|
||||||
// Forward the event to the controller listener
|
// Forward the event to the controller listener
|
||||||
controller->cbs->on_error(controller, controller->cbs_userdata);
|
controller->cbs->on_ended(controller, error, controller->cbs_userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -27,7 +28,7 @@ sc_controller_init(struct sc_controller *controller, sc_socket control_socket,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct sc_receiver_callbacks receiver_cbs = {
|
static const struct sc_receiver_callbacks receiver_cbs = {
|
||||||
.on_error = sc_controller_receiver_on_error,
|
.on_ended = sc_controller_receiver_on_ended,
|
||||||
};
|
};
|
||||||
|
|
||||||
ok = sc_receiver_init(&controller->receiver, control_socket, &receiver_cbs,
|
ok = sc_receiver_init(&controller->receiver, control_socket, &receiver_cbs,
|
||||||
|
@ -55,7 +56,7 @@ sc_controller_init(struct sc_controller *controller, sc_socket control_socket,
|
||||||
controller->control_socket = control_socket;
|
controller->control_socket = control_socket;
|
||||||
controller->stopped = false;
|
controller->stopped = false;
|
||||||
|
|
||||||
assert(cbs && cbs->on_error);
|
assert(cbs && cbs->on_ended);
|
||||||
controller->cbs = cbs;
|
controller->cbs = cbs;
|
||||||
controller->cbs_userdata = cbs_userdata;
|
controller->cbs_userdata = cbs_userdata;
|
||||||
|
|
||||||
|
@ -110,21 +111,30 @@ sc_controller_push_msg(struct sc_controller *controller,
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
process_msg(struct sc_controller *controller,
|
process_msg(struct sc_controller *controller,
|
||||||
const struct sc_control_msg *msg) {
|
const struct sc_control_msg *msg, bool *eos) {
|
||||||
static uint8_t serialized_msg[SC_CONTROL_MSG_MAX_SIZE];
|
static uint8_t serialized_msg[SC_CONTROL_MSG_MAX_SIZE];
|
||||||
size_t length = sc_control_msg_serialize(msg, serialized_msg);
|
size_t length = sc_control_msg_serialize(msg, serialized_msg);
|
||||||
if (!length) {
|
if (!length) {
|
||||||
|
*eos = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t w =
|
ssize_t w =
|
||||||
net_send_all(controller->control_socket, serialized_msg, length);
|
net_send_all(controller->control_socket, serialized_msg, length);
|
||||||
return (size_t) w == length;
|
if ((size_t) w != length) {
|
||||||
|
*eos = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
run_controller(void *data) {
|
run_controller(void *data) {
|
||||||
struct sc_controller *controller = data;
|
struct sc_controller *controller = data;
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sc_mutex_lock(&controller->mutex);
|
sc_mutex_lock(&controller->mutex);
|
||||||
while (!controller->stopped
|
while (!controller->stopped
|
||||||
|
@ -134,6 +144,7 @@ run_controller(void *data) {
|
||||||
if (controller->stopped) {
|
if (controller->stopped) {
|
||||||
// stop immediately, do not process further msgs
|
// stop immediately, do not process further msgs
|
||||||
sc_mutex_unlock(&controller->mutex);
|
sc_mutex_unlock(&controller->mutex);
|
||||||
|
LOGD("Controller stopped");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,20 +152,21 @@ run_controller(void *data) {
|
||||||
struct sc_control_msg msg = sc_vecdeque_pop(&controller->queue);
|
struct sc_control_msg msg = sc_vecdeque_pop(&controller->queue);
|
||||||
sc_mutex_unlock(&controller->mutex);
|
sc_mutex_unlock(&controller->mutex);
|
||||||
|
|
||||||
bool ok = process_msg(controller, &msg);
|
bool eos;
|
||||||
|
bool ok = process_msg(controller, &msg, &eos);
|
||||||
sc_control_msg_destroy(&msg);
|
sc_control_msg_destroy(&msg);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGD("Could not write msg to socket");
|
if (eos) {
|
||||||
goto error;
|
LOGD("Controller stopped (socket closed)");
|
||||||
|
} // else error already logged
|
||||||
|
error = !eos;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller->cbs->on_ended(controller, error, controller->cbs_userdata);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
|
||||||
controller->cbs->on_error(controller, controller->cbs_userdata);
|
|
||||||
|
|
||||||
return 1; // ignored
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -28,7 +28,8 @@ struct sc_controller {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_controller_callbacks {
|
struct sc_controller_callbacks {
|
||||||
void (*on_error)(struct sc_controller *controller, void *userdata);
|
void (*on_ended)(struct sc_controller *controller, bool error,
|
||||||
|
void *userdata);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -21,7 +21,7 @@ sc_receiver_init(struct sc_receiver *receiver, sc_socket control_socket,
|
||||||
receiver->acksync = NULL;
|
receiver->acksync = NULL;
|
||||||
receiver->uhid_devices = NULL;
|
receiver->uhid_devices = NULL;
|
||||||
|
|
||||||
assert(cbs && cbs->on_error);
|
assert(cbs && cbs->on_ended);
|
||||||
receiver->cbs = cbs;
|
receiver->cbs = cbs;
|
||||||
receiver->cbs_userdata = cbs_userdata;
|
receiver->cbs_userdata = cbs_userdata;
|
||||||
|
|
||||||
|
@ -134,12 +134,15 @@ run_receiver(void *data) {
|
||||||
static uint8_t buf[DEVICE_MSG_MAX_SIZE];
|
static uint8_t buf[DEVICE_MSG_MAX_SIZE];
|
||||||
size_t head = 0;
|
size_t head = 0;
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
assert(head < DEVICE_MSG_MAX_SIZE);
|
assert(head < DEVICE_MSG_MAX_SIZE);
|
||||||
ssize_t r = net_recv(receiver->control_socket, buf + head,
|
ssize_t r = net_recv(receiver->control_socket, buf + head,
|
||||||
DEVICE_MSG_MAX_SIZE - head);
|
DEVICE_MSG_MAX_SIZE - head);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
LOGD("Receiver stopped");
|
LOGD("Receiver stopped");
|
||||||
|
// device disconnected: keep error=false
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +150,7 @@ run_receiver(void *data) {
|
||||||
ssize_t consumed = process_msgs(receiver, buf, head);
|
ssize_t consumed = process_msgs(receiver, buf, head);
|
||||||
if (consumed == -1) {
|
if (consumed == -1) {
|
||||||
// an error occurred
|
// an error occurred
|
||||||
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +161,7 @@ run_receiver(void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver->cbs->on_error(receiver, receiver->cbs_userdata);
|
receiver->cbs->on_ended(receiver, error, receiver->cbs_userdata);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ struct sc_receiver {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_receiver_callbacks {
|
struct sc_receiver_callbacks {
|
||||||
void (*on_error)(struct sc_receiver *receiver, void *userdata);
|
void (*on_ended)(struct sc_receiver *receiver, bool error, void *userdata);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -269,13 +269,18 @@ sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_controller_on_error(struct sc_controller *controller, void *userdata) {
|
sc_controller_on_ended(struct sc_controller *controller, bool error,
|
||||||
|
void *userdata) {
|
||||||
// Note: this function may be called twice, once from the controller thread
|
// Note: this function may be called twice, once from the controller thread
|
||||||
// and once from the receiver thread
|
// and once from the receiver thread
|
||||||
(void) controller;
|
(void) controller;
|
||||||
(void) userdata;
|
(void) userdata;
|
||||||
|
|
||||||
PUSH_EVENT(SC_EVENT_CONTROLLER_ERROR);
|
if (error) {
|
||||||
|
PUSH_EVENT(SC_EVENT_CONTROLLER_ERROR);
|
||||||
|
} else {
|
||||||
|
PUSH_EVENT(SC_EVENT_DEVICE_DISCONNECTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -567,7 +572,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
|
|
||||||
if (options->control) {
|
if (options->control) {
|
||||||
static const struct sc_controller_callbacks controller_cbs = {
|
static const struct sc_controller_callbacks controller_cbs = {
|
||||||
.on_error = sc_controller_on_error,
|
.on_ended = sc_controller_on_ended,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!sc_controller_init(&s->controller, s->server.control_socket,
|
if (!sc_controller_init(&s->controller, s->server.control_socket,
|
||||||
|
|
Loading…
Reference in a new issue