Skip to content
Snippets Groups Projects
Commit f069c3a5 authored by Slava Monich's avatar Slava Monich
Browse files

[gbinder] Corner cases for abandoned loopers. JB#42956

If the last GBinderIpc reference was dropped by the looper thread,
the exit flag wasn't set by gbinder_ipc_looper_stop() and such
looper thread kept hanging forever. Also, that flag wasn't checked
by gbinder_driver_read(), and even though it's even less likely
to cause any trouble in real life, let's fix that too.
parent b84194e8
No related branches found
No related tags found
No related merge requests found
......@@ -953,7 +953,7 @@ gbinder_driver_read(
if (ret >= 0) {
/* Loop until we have handled all the incoming commands */
gbinder_driver_handle_commands(self, reg, handler, &rb);
while (rb.buf.consumed) {
while (rb.buf.consumed && gbinder_handler_can_loop(handler)) {
ret = gbinder_driver_write_read(self, NULL, &rb.buf);
if (ret >= 0) {
gbinder_driver_handle_commands(self, reg, handler, &rb);
......
......@@ -36,6 +36,7 @@
#include "gbinder_types_p.h"
typedef struct gbinder_handler_functions {
gboolean (*can_loop)(GBinderHandler* handler);
GBinderLocalReply* (*transact)(GBinderHandler* handler,
GBinderLocalObject* obj, GBinderRemoteRequest* req, guint code,
guint flags, int* status);
......@@ -47,6 +48,14 @@ struct gbinder_handler {
/* Inline wrappers */
GBINDER_INLINE_FUNC
gboolean
gbinder_handler_can_loop(
GBinderHandler* self)
{
return self && self->f->can_loop && self->f->can_loop(self);
}
GBINDER_INLINE_FUNC
GBinderLocalReply*
gbinder_handler_transact(
......
......@@ -606,6 +606,16 @@ gbinder_ipc_looper_count_primary(
return n;
}
static
gboolean
gbinder_ipc_looper_can_loop(
GBinderHandler* handler)
{
GBinderIpcLooper* looper = G_CAST(handler,GBinderIpcLooper,handler);
return !g_atomic_int_get(&looper->exit);
}
static
GBinderLocalReply*
gbinder_ipc_looper_transact(
......@@ -824,6 +834,7 @@ gbinder_ipc_looper_new(
/* Note: this call can actually fail */
if (!pipe(fd)) {
static const GBinderHandlerFunctions handler_functions = {
.can_loop = gbinder_ipc_looper_can_loop,
.transact = gbinder_ipc_looper_transact
};
GError* error = NULL;
......@@ -896,13 +907,15 @@ gbinder_ipc_looper_stop(
GBinderIpcLooper* looper)
{
/* Caller checks looper for NULL */
if (looper->thread && looper->thread != g_thread_self()) {
guint8 done = TX_DONE;
if (looper->thread) {
GDEBUG("Stopping looper %s", looper->name);
g_atomic_int_set(&looper->exit, TRUE);
if (write(looper->pipefd[1], &done, sizeof(done)) <= 0) {
looper->thread = NULL;
if (looper->thread != g_thread_self()) {
guint8 done = TX_DONE;
if (write(looper->pipefd[1], &done, sizeof(done)) <= 0) {
looper->thread = NULL;
}
}
}
}
......@@ -1421,7 +1434,8 @@ gbinder_ipc_tx_internal_exec(
GBinderIpcTxPriv* priv)
{
static const GBinderHandlerFunctions handler_fn = {
gbinder_ipc_tx_handler_transact
.can_loop = NULL,
.transact = gbinder_ipc_tx_handler_transact
};
GBinderIpcTxInternal* tx = gbinder_ipc_tx_internal_cast(priv);
GBinderIpcTx* pub = &priv->pub;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment