From 536143c1d708dcf23d9978bd7d861125d11273a7 Mon Sep 17 00:00:00 2001 From: Slava Monich <slava.monich@jolla.com> Date: Wed, 20 Jan 2021 18:56:57 +0200 Subject: [PATCH] [gbinder] Fixed a threading issue. JB#42956 Make sure that transaction handlers don't get invoked on a worker thread. It was possible in cases if an incoming transaction arrives while we are waiting for response from an asynchronous call to servicemanager (which is actually a synchronous call made on a worker thread). Invoking callbacks on a worker thread would completely break libgbinder's synchronization model. It was a pretty unlikely scenario, though. --- src/gbinder_client.c | 107 +++++---- src/gbinder_client_p.h | 22 +- src/gbinder_ipc.c | 212 ++++++++++++------ src/gbinder_ipc.h | 46 ++-- src/gbinder_servicemanager.c | 27 ++- src/gbinder_servicemanager_aidl.c | 27 ++- src/gbinder_servicemanager_hidl.c | 27 ++- src/gbinder_servicemanager_p.h | 15 +- src/gbinder_types_p.h | 5 +- unit/unit_ipc/unit_ipc.c | 25 ++- .../unit_servicemanager/unit_servicemanager.c | 13 +- unit/unit_servicename/unit_servicename.c | 13 +- unit/unit_servicepoll/unit_servicepoll.c | 13 +- 13 files changed, 353 insertions(+), 199 deletions(-) diff --git a/src/gbinder_client.c b/src/gbinder_client.c index d54bbe6..4d9c0e3 100644 --- a/src/gbinder_client.c +++ b/src/gbinder_client.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -178,6 +178,66 @@ gbinder_client_transact_destroy( g_slice_free(GBinderClientTx, tx); } +/*==========================================================================* + * Internal interface + *==========================================================================*/ + +GBinderRemoteReply* +gbinder_client_transact_sync_reply2( + GBinderClient* self, + guint32 code, + GBinderLocalRequest* req, + int* status, + const GBinderIpcSyncApi* api) +{ + if (G_LIKELY(self)) { + GBinderRemoteObject* obj = self->remote; + + if (G_LIKELY(!obj->dead)) { + if (!req) { + const GBinderClientIfaceRange* r = gbinder_client_find_range + (gbinder_client_cast(self), code); + + /* Default empty request (just the header, no parameters) */ + if (r) { + req = r->basic_req; + } + } + return api->sync_reply(obj->ipc, obj->handle, code, req, status); + } + GDEBUG("Refusing to perform transaction with a dead object"); + } + return NULL; +} + +int +gbinder_client_transact_sync_oneway2( + GBinderClient* self, + guint32 code, + GBinderLocalRequest* req, + const GBinderIpcSyncApi* api) +{ + if (G_LIKELY(self)) { + GBinderRemoteObject* obj = self->remote; + + if (G_LIKELY(!obj->dead)) { + if (!req) { + const GBinderClientIfaceRange* r = gbinder_client_find_range + (gbinder_client_cast(self), code); + + /* Default empty request (just the header, no parameters) */ + if (r) { + req = r->basic_req; + } + } + return api->sync_oneway(obj->ipc, obj->handle, code, req); + } + GDEBUG("Refusing to perform transaction with a dead object"); + return (-ESTALE); + } + return (-EINVAL); +} + /*==========================================================================* * Interface *==========================================================================*/ @@ -319,25 +379,8 @@ gbinder_client_transact_sync_reply( GBinderLocalRequest* req, int* status) { - if (G_LIKELY(self)) { - GBinderRemoteObject* obj = self->remote; - - if (G_LIKELY(!obj->dead)) { - if (!req) { - const GBinderClientIfaceRange* r = gbinder_client_find_range - (gbinder_client_cast(self), code); - - /* Default empty request (just the header, no parameters) */ - if (r) { - req = r->basic_req; - } - } - return gbinder_ipc_transact_sync_reply(obj->ipc, obj->handle, - code, req, status); - } - GDEBUG("Refusing to perform transaction with a dead object"); - } - return NULL; + return gbinder_client_transact_sync_reply2(self, code, req, status, + &gbinder_ipc_sync_main); } int @@ -346,26 +389,8 @@ gbinder_client_transact_sync_oneway( guint32 code, GBinderLocalRequest* req) { - if (G_LIKELY(self)) { - GBinderRemoteObject* obj = self->remote; - - if (G_LIKELY(!obj->dead)) { - if (!req) { - const GBinderClientIfaceRange* r = gbinder_client_find_range - (gbinder_client_cast(self), code); - - /* Default empty request (just the header, no parameters) */ - if (r) { - req = r->basic_req; - } - } - return gbinder_ipc_transact_sync_oneway(obj->ipc, obj->handle, - code, req); - } - GDEBUG("Refusing to perform transaction with a dead object"); - return (-ESTALE); - } - return (-EINVAL); + return gbinder_client_transact_sync_oneway2(self, code, req, + &gbinder_ipc_sync_main); } gulong diff --git a/src/gbinder_client_p.h b/src/gbinder_client_p.h index 55bae03..3b3f5c3 100644 --- a/src/gbinder_client_p.h +++ b/src/gbinder_client_p.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -41,6 +41,24 @@ struct gbinder_client { GBinderRemoteObject* remote; }; +GBinderRemoteReply* +gbinder_client_transact_sync_reply2( + GBinderClient* self, + guint32 code, + GBinderLocalRequest* req, + int* status, + const GBinderIpcSyncApi* api) + G_GNUC_WARN_UNUSED_RESULT + GBINDER_INTERNAL; + +int +gbinder_client_transact_sync_oneway2( + GBinderClient* self, + guint32 code, + GBinderLocalRequest* req, + const GBinderIpcSyncApi* api) + GBINDER_INTERNAL; + #define gbinder_client_ipc(client) ((client)->remote->ipc) #endif /* GBINDER_CLIENT_PRIVATE_H */ diff --git a/src/gbinder_ipc.c b/src/gbinder_ipc.c index a7c6f2e..5831474 100644 --- a/src/gbinder_ipc.c +++ b/src/gbinder_ipc.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -210,6 +210,23 @@ GBinderIpcLooper* gbinder_ipc_looper_new( GBinderIpc* ipc); +static +GBinderRemoteReply* +gbinder_ipc_transact_sync_reply_worker( + GBinderIpc* self, + guint32 handle, + guint32 code, + GBinderLocalRequest* req, + int* status); + +static +int +gbinder_ipc_transact_sync_oneway_worker( + GBinderIpc* self, + guint32 handle, + guint32 code, + GBinderLocalRequest* req); + /*==========================================================================* * Utilities *==========================================================================*/ @@ -1433,30 +1450,15 @@ void gbinder_ipc_tx_internal_exec( GBinderIpcTxPriv* priv) { - static const GBinderHandlerFunctions handler_fn = { - .can_loop = NULL, - .transact = gbinder_ipc_tx_handler_transact - }; GBinderIpcTxInternal* tx = gbinder_ipc_tx_internal_cast(priv); - GBinderIpcTx* pub = &priv->pub; - GBinderIpc* self = pub->ipc; - GBinderObjectRegistry* reg = &self->priv->object_registry; - GBinderHandler handler = { &handler_fn }; + GBinderIpc* ipc = priv->pub.ipc; - /* Perform synchronous transaction */ if (tx->flags & GBINDER_TX_FLAG_ONEWAY) { - tx->status = gbinder_driver_transact(self->driver, reg, &handler, - tx->handle, tx->code, tx->req, NULL); + tx->status = gbinder_ipc_transact_sync_oneway_worker(ipc, tx->handle, + tx->code, tx->req); } else { - tx->reply = gbinder_remote_reply_new(&self->priv->object_registry); - tx->status = gbinder_driver_transact(self->driver, reg, &handler, - tx->handle, tx->code, tx->req, tx->reply); - if (tx->status != GBINDER_STATUS_OK && - gbinder_remote_reply_is_empty(tx->reply)) { - /* Drop useless reply */ - gbinder_remote_reply_unref(tx->reply); - tx->reply = NULL; - } + tx->reply = gbinder_ipc_transact_sync_reply_worker(ipc, tx->handle, + tx->code, tx->req, &tx->status); } } @@ -1579,6 +1581,128 @@ gbinder_ipc_tx_proc( gbinder_idle_callback_schedule(tx->completion); } +/*==========================================================================* + * GBinderIpcSyncApi for worker threads + *==========================================================================*/ + +static +GBinderRemoteReply* +gbinder_ipc_transact_sync_reply_worker( + GBinderIpc* self, + guint32 handle, + guint32 code, + GBinderLocalRequest* req, + int* status) +{ + /* Must be invoked on worker thread */ + if (G_LIKELY(self)) { + static const GBinderHandlerFunctions handler_fn = { + .can_loop = NULL, + .transact = gbinder_ipc_tx_handler_transact + }; + GBinderHandler handler = { &handler_fn }; + GBinderIpcPriv* priv = self->priv; + GBinderObjectRegistry* reg = &priv->object_registry; + GBinderRemoteReply* reply = gbinder_remote_reply_new(reg); + int ret = gbinder_driver_transact(self->driver, reg, &handler, + handle, code, req, reply); + + if (status) *status = ret; + if (ret == GBINDER_STATUS_OK || !gbinder_remote_reply_is_empty(reply)) { + return reply; + } else { + gbinder_remote_reply_unref(reply); + } + } else { + if (status) *status = (-EINVAL); + } + return NULL; +} + +static +int +gbinder_ipc_transact_sync_oneway_worker( + GBinderIpc* self, + guint32 handle, + guint32 code, + GBinderLocalRequest* req) +{ + /* Must be invoked on worker thread */ + if (G_LIKELY(self)) { + static const GBinderHandlerFunctions handler_fn = { + .can_loop = NULL, + .transact = gbinder_ipc_tx_handler_transact + }; + GBinderHandler handler = { &handler_fn }; + GBinderIpcPriv* priv = self->priv; + + return gbinder_driver_transact(self->driver, &priv->object_registry, + &handler, handle, code, req, NULL); + } else { + return (-EINVAL); + } +} + +const GBinderIpcSyncApi gbinder_ipc_sync_worker = { + .sync_reply = gbinder_ipc_transact_sync_reply_worker, + .sync_oneway = gbinder_ipc_transact_sync_oneway_worker +}; + +/*==========================================================================* + * GBinderIpcSyncApi for the main thread + *==========================================================================*/ + +static +GBinderRemoteReply* +gbinder_ipc_transact_sync_reply( + GBinderIpc* self, + guint32 handle, + guint32 code, + GBinderLocalRequest* req, + int* status) +{ + if (G_LIKELY(self)) { + GBinderIpcPriv* priv = self->priv; + GBinderObjectRegistry* reg = &priv->object_registry; + GBinderRemoteReply* reply = gbinder_remote_reply_new(reg); + int ret = gbinder_driver_transact(self->driver, reg, NULL, handle, + code, req, reply); + + if (status) *status = ret; + if (ret == GBINDER_STATUS_OK || !gbinder_remote_reply_is_empty(reply)) { + return reply; + } else { + gbinder_remote_reply_unref(reply); + } + } else { + if (status) *status = (-EINVAL); + } + return NULL; +} + +static +int +gbinder_ipc_transact_sync_oneway( + GBinderIpc* self, + guint32 handle, + guint32 code, + GBinderLocalRequest* req) +{ + if (G_LIKELY(self)) { + GBinderIpcPriv* priv = self->priv; + + return gbinder_driver_transact(self->driver, &priv->object_registry, + NULL, handle, code, req, NULL); + } else { + return (-EINVAL); + } +} + +const GBinderIpcSyncApi gbinder_ipc_sync_main = { + .sync_reply = gbinder_ipc_transact_sync_reply, + .sync_oneway = gbinder_ipc_transact_sync_oneway +}; + /*==========================================================================* * Interface *==========================================================================*/ @@ -1652,50 +1776,6 @@ gbinder_ipc_object_registry( return G_LIKELY(self) ? &self->priv->object_registry : NULL; } -GBinderRemoteReply* -gbinder_ipc_transact_sync_reply( - GBinderIpc* self, - guint32 handle, - guint32 code, - GBinderLocalRequest* req, - int* status) -{ - if (G_LIKELY(self)) { - GBinderIpcPriv* priv = self->priv; - GBinderObjectRegistry* reg = &priv->object_registry; - GBinderRemoteReply* reply = gbinder_remote_reply_new(reg); - int ret = gbinder_driver_transact(self->driver, reg, NULL, handle, - code, req, reply); - - if (status) *status = ret; - if (ret == GBINDER_STATUS_OK || !gbinder_remote_reply_is_empty(reply)) { - return reply; - } else { - gbinder_remote_reply_unref(reply); - } - } else { - if (status) *status = (-EINVAL); - } - return NULL; -} - -int -gbinder_ipc_transact_sync_oneway( - GBinderIpc* self, - guint32 handle, - guint32 code, - GBinderLocalRequest* req) -{ - if (G_LIKELY(self)) { - GBinderIpcPriv* priv = self->priv; - - return gbinder_driver_transact(self->driver, &priv->object_registry, - NULL, handle, code, req, NULL); - } else { - return (-EINVAL); - } -} - gulong gbinder_ipc_transact( GBinderIpc* self, diff --git a/src/gbinder_ipc.h b/src/gbinder_ipc.h index 87fb4a8..09e7697 100644 --- a/src/gbinder_ipc.h +++ b/src/gbinder_ipc.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -67,6 +67,31 @@ void int status, void* user_data); +typedef +GBinderRemoteReply* +(*GBinderIpcSyncReplyFunc)( + GBinderIpc* ipc, + guint32 handle, + guint32 code, + GBinderLocalRequest* req, + int* status); + +typedef +int +(*GBinderIpcSyncOnewayFunc)( + GBinderIpc* ipc, + guint32 handle, + guint32 code, + GBinderLocalRequest* req); + +struct gbinder_ipc_sync_api { + GBinderIpcSyncReplyFunc sync_reply; + GBinderIpcSyncOnewayFunc sync_oneway; +}; + +extern const GBinderIpcSyncApi gbinder_ipc_sync_main GBINDER_INTERNAL; +extern const GBinderIpcSyncApi gbinder_ipc_sync_worker GBINDER_INTERNAL; + GBinderIpc* gbinder_ipc_new( const char* dev) @@ -111,23 +136,6 @@ gbinder_ipc_invalidate_remote_handle( guint32 handle) GBINDER_INTERNAL; -GBinderRemoteReply* -gbinder_ipc_transact_sync_reply( - GBinderIpc* ipc, - guint32 handle, - guint32 code, - GBinderLocalRequest* req, - int* status) - GBINDER_INTERNAL; - -int -gbinder_ipc_transact_sync_oneway( - GBinderIpc* ipc, - guint32 handle, - guint32 code, - GBinderLocalRequest* req) - GBINDER_INTERNAL; - gulong gbinder_ipc_transact( GBinderIpc* ipc, diff --git a/src/gbinder_servicemanager.c b/src/gbinder_servicemanager.c index 45dbb27..71b1aba 100644 --- a/src/gbinder_servicemanager.c +++ b/src/gbinder_servicemanager.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -199,7 +199,8 @@ gbinder_servicemanager_list_tx_exec( { GBinderServiceManagerListTxData* data = tx->user_data; - data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->list(data->sm); + data->result = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)-> + list(data->sm, &gbinder_ipc_sync_worker); } static @@ -243,8 +244,9 @@ gbinder_servicemanager_get_service_tx_exec( { GBinderServiceManagerGetServiceTxData* data = tx->user_data; - data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->get_service - (data->sm, data->name, &data->status); + data->obj = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)-> + get_service(data->sm, data->name, &data->status, + &gbinder_ipc_sync_worker); } static @@ -286,8 +288,8 @@ gbinder_servicemanager_add_service_tx_exec( { GBinderServiceManagerAddServiceTxData* data = tx->user_data; - data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)->add_service - (data->sm, data->name, data->obj); + data->status = GBINDER_SERVICEMANAGER_GET_CLASS(data->sm)-> + add_service(data->sm, data->name, data->obj, &gbinder_ipc_sync_worker); } static @@ -776,7 +778,8 @@ gbinder_servicemanager_list_sync( GBinderServiceManager* self) { if (G_LIKELY(self)) { - return GBINDER_SERVICEMANAGER_GET_CLASS(self)->list(self); + return GBINDER_SERVICEMANAGER_GET_CLASS(self)-> + list(self, &gbinder_ipc_sync_main); } return NULL; } @@ -815,8 +818,8 @@ gbinder_servicemanager_get_service_sync( GBinderRemoteObject* obj = NULL; if (G_LIKELY(self) && name) { - obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)->get_service - (self, name, status); + obj = GBINDER_SERVICEMANAGER_GET_CLASS(self)-> + get_service(self, name, status, &gbinder_ipc_sync_main); if (obj) { GBinderServiceManagerPriv* priv = self->priv; @@ -866,8 +869,8 @@ gbinder_servicemanager_add_service_sync( GBinderLocalObject* obj) { if (G_LIKELY(self) && name && obj) { - return GBINDER_SERVICEMANAGER_GET_CLASS(self)->add_service - (self, name, obj); + return GBINDER_SERVICEMANAGER_GET_CLASS(self)-> + add_service(self, name, obj, &gbinder_ipc_sync_main); } else { return (-EINVAL); } diff --git a/src/gbinder_servicemanager_aidl.c b/src/gbinder_servicemanager_aidl.c index 08322ee..3efb39d 100644 --- a/src/gbinder_servicemanager_aidl.c +++ b/src/gbinder_servicemanager_aidl.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -35,9 +35,9 @@ #include "gbinder_servicemanager_aidl.h" #include "gbinder_servicepoll.h" #include "gbinder_eventloop_p.h" +#include "gbinder_client_p.h" #include "gbinder_log.h" -#include <gbinder_client.h> #include <gbinder_local_request.h> #include <gbinder_remote_reply.h> @@ -172,7 +172,8 @@ gbinder_servicemanager_aidl_add_service_req( static char** gbinder_servicemanager_aidl_list( - GBinderServiceManager* manager) + GBinderServiceManager* manager, + const GBinderIpcSyncApi* api) { GPtrArray* list = g_ptr_array_new(); GBinderClient* client = manager->client; @@ -181,8 +182,8 @@ gbinder_servicemanager_aidl_list( GBinderLocalRequest* req = klass->list_services_req(client, 0); GBinderRemoteReply* reply; - while ((reply = gbinder_client_transact_sync_reply(client, - LIST_SERVICES_TRANSACTION, req, NULL)) != NULL) { + while ((reply = gbinder_client_transact_sync_reply2(client, + LIST_SERVICES_TRANSACTION, req, NULL, api)) != NULL) { char* service = gbinder_remote_reply_read_string16(reply); gbinder_remote_reply_unref(reply); @@ -205,15 +206,16 @@ GBinderRemoteObject* gbinder_servicemanager_aidl_get_service( GBinderServiceManager* self, const char* name, - int* status) + int* status, + const GBinderIpcSyncApi* api) { GBinderRemoteObject* obj; GBinderRemoteReply* reply; GBinderLocalRequest* req = gbinder_client_new_request(self->client); gbinder_local_request_append_string16(req, name); - reply = gbinder_client_transact_sync_reply(self->client, - CHECK_SERVICE_TRANSACTION, req, status); + reply = gbinder_client_transact_sync_reply2(self->client, + CHECK_SERVICE_TRANSACTION, req, status, api); obj = gbinder_remote_reply_read_object(reply); gbinder_remote_reply_unref(reply); @@ -226,14 +228,15 @@ int gbinder_servicemanager_aidl_add_service( GBinderServiceManager* manager, const char* name, - GBinderLocalObject* obj) + GBinderLocalObject* obj, + const GBinderIpcSyncApi* api) { int status; GBinderClient* client = manager->client; GBinderLocalRequest* req = GBINDER_SERVICEMANAGER_AIDL_GET_CLASS (manager)->add_service_req(client, name, obj); - GBinderRemoteReply* reply = gbinder_client_transact_sync_reply(client, - ADD_SERVICE_TRANSACTION, req, &status); + GBinderRemoteReply* reply = gbinder_client_transact_sync_reply2(client, + ADD_SERVICE_TRANSACTION, req, &status, api); gbinder_remote_reply_unref(reply); gbinder_local_request_unref(req); diff --git a/src/gbinder_servicemanager_hidl.c b/src/gbinder_servicemanager_hidl.c index 242fd85..69c60f5 100644 --- a/src/gbinder_servicemanager_hidl.c +++ b/src/gbinder_servicemanager_hidl.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -31,9 +31,9 @@ */ #include "gbinder_servicemanager_p.h" +#include "gbinder_client_p.h" #include "gbinder_log.h" -#include <gbinder_client.h> #include <gbinder_local_object.h> #include <gbinder_local_request.h> #include <gbinder_remote_reply.h> @@ -147,11 +147,12 @@ gbinder_servicemanager_hidl_notification( static char** gbinder_servicemanager_hidl_list( - GBinderServiceManager* self) + GBinderServiceManager* self, + const GBinderIpcSyncApi* api) { GBinderLocalRequest* req = gbinder_client_new_request(self->client); - GBinderRemoteReply* reply = gbinder_client_transact_sync_reply - (self->client, LIST_TRANSACTION, req, NULL); + GBinderRemoteReply* reply = gbinder_client_transact_sync_reply2 + (self->client, LIST_TRANSACTION, req, NULL, api); gbinder_local_request_unref(req); if (reply) { @@ -178,7 +179,8 @@ GBinderRemoteObject* gbinder_servicemanager_hidl_get_service( GBinderServiceManager* self, const char* fqinstance, - int* status) + int* status, + const GBinderIpcSyncApi* api) { /* e.g. "android.hardware.radio@1.1::IRadio/slot1" */ const char* sep = strchr(fqinstance, '/'); @@ -193,8 +195,8 @@ gbinder_servicemanager_hidl_get_service( gbinder_local_request_append_hidl_string(req, fqname); gbinder_local_request_append_hidl_string(req, name); - reply = gbinder_client_transact_sync_reply(self->client, - GET_TRANSACTION, req, status); + reply = gbinder_client_transact_sync_reply2(self->client, + GET_TRANSACTION, req, status, api); if (reply) { GBinderReader reader; @@ -225,7 +227,8 @@ int gbinder_servicemanager_hidl_add_service( GBinderServiceManager* self, const char* name, - GBinderLocalObject* obj) + GBinderLocalObject* obj, + const GBinderIpcSyncApi* api) { int status; GBinderRemoteReply* reply; @@ -235,8 +238,8 @@ gbinder_servicemanager_hidl_add_service( gbinder_local_request_append_hidl_string(req, name); gbinder_local_request_append_local_object(req, obj); - reply = gbinder_client_transact_sync_reply(self->client, - ADD_TRANSACTION, req, &status); + reply = gbinder_client_transact_sync_reply2(self->client, + ADD_TRANSACTION, req, &status, api); gbinder_remote_reply_unref(reply); gbinder_local_request_unref(req); diff --git a/src/gbinder_servicemanager_p.h b/src/gbinder_servicemanager_p.h index 5939026..ac472c3 100644 --- a/src/gbinder_servicemanager_p.h +++ b/src/gbinder_servicemanager_p.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -66,12 +66,11 @@ typedef struct gbinder_servicemanager_class { const char* default_device; /* Methods (synchronous) */ - char** (*list)(GBinderServiceManager* self); - GBinderRemoteObject* (*get_service) - (GBinderServiceManager* self, const char* name, int* status); - int (*add_service) - (GBinderServiceManager* self, const char* name, - GBinderLocalObject* obj); + char** (*list)(GBinderServiceManager* self, const GBinderIpcSyncApi* api); + GBinderRemoteObject* (*get_service)(GBinderServiceManager* self, + const char* name, int* status, const GBinderIpcSyncApi* api); + int (*add_service)(GBinderServiceManager* self, const char* name, + GBinderLocalObject* obj, const GBinderIpcSyncApi* api); /* Checking/normalizing watch names */ GBINDER_SERVICEMANAGER_NAME_CHECK (*check_name) diff --git a/src/gbinder_types_p.h b/src/gbinder_types_p.h index 580a915..aaf2284 100644 --- a/src/gbinder_types_p.h +++ b/src/gbinder_types_p.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -45,6 +45,7 @@ typedef struct gbinder_output_data GBinderOutputData; typedef struct gbinder_rpc_protocol GBinderRpcProtocol; typedef struct gbinder_servicepoll GBinderServicePoll; typedef struct gbinder_ipc_looper_tx GBinderIpcLooperTx; +typedef struct gbinder_ipc_sync_api GBinderIpcSyncApi; #define GBINDER_INLINE_FUNC static inline #define GBINDER_INTERNAL G_GNUC_INTERNAL diff --git a/unit/unit_ipc/unit_ipc.c b/unit/unit_ipc/unit_ipc.c index b21b8a6..282aba4 100644 --- a/unit/unit_ipc/unit_ipc.c +++ b/unit/unit_ipc/unit_ipc.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -84,10 +84,16 @@ test_null( g_assert(!gbinder_ipc_ref(null)); gbinder_ipc_unref(null); - g_assert(!gbinder_ipc_transact_sync_reply(null, 0, 0, NULL, NULL)); - g_assert(!gbinder_ipc_transact_sync_reply(null, 0, 0, NULL, &status)); - g_assert(status == (-EINVAL)); - g_assert(gbinder_ipc_transact_sync_oneway(null, 0, 0, NULL) == (-EINVAL)); + g_assert(!gbinder_ipc_sync_main.sync_reply(null, 0, 0, NULL, NULL)); + g_assert(!gbinder_ipc_sync_main.sync_reply(null, 0, 0, NULL, &status)); + g_assert_cmpint(status, == ,-EINVAL); + g_assert(!gbinder_ipc_sync_worker.sync_reply(null, 0, 0, NULL, NULL)); + g_assert(!gbinder_ipc_sync_worker.sync_reply(null, 0, 0, NULL, &status)); + g_assert_cmpint(status, == ,-EINVAL); + g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(null, 0, 0, NULL), == , + -EINVAL); + g_assert_cmpint(gbinder_ipc_sync_worker.sync_oneway(null, 0, 0, NULL), == , + -EINVAL); g_assert(!gbinder_ipc_transact(null, 0, 0, 0, NULL, NULL, NULL, NULL)); g_assert(!gbinder_ipc_transact_custom(null, NULL, NULL, NULL, NULL)); g_assert(!gbinder_ipc_object_registry(null)); @@ -187,8 +193,7 @@ test_sync_oneway( GBinderLocalRequest* req = gbinder_local_request_new(io, NULL); test_binder_br_transaction_complete(fd); - g_assert(gbinder_ipc_transact_sync_oneway(ipc, 0, 1, req) == - GBINDER_STATUS_OK); + g_assert_cmpint(gbinder_ipc_sync_main.sync_oneway(ipc, 0, 1, req), == ,0); gbinder_local_request_unref(req); gbinder_ipc_unref(ipc); gbinder_ipc_exit(); @@ -225,7 +230,7 @@ test_sync_reply_ok_status( test_binder_br_noop(fd); test_binder_br_reply(fd, handle, code, data->bytes); - tx_reply = gbinder_ipc_transact_sync_reply(ipc, handle, code, req, status); + tx_reply = gbinder_ipc_sync_main.sync_reply(ipc, handle, code, req, status); g_assert(tx_reply); result_out = gbinder_remote_reply_read_string16(tx_reply); @@ -275,7 +280,7 @@ test_sync_reply_error( test_binder_br_noop(fd); test_binder_br_reply_status(fd, expected_status); - g_assert(!gbinder_ipc_transact_sync_reply(ipc, handle, code, req, &status)); + g_assert(!gbinder_ipc_sync_main.sync_reply(ipc,handle,code,req,&status)); g_assert(status == expected_status); gbinder_local_request_unref(req); diff --git a/unit/unit_servicemanager/unit_servicemanager.c b/unit/unit_servicemanager/unit_servicemanager.c index 7b947cf..48ada68 100644 --- a/unit/unit_servicemanager/unit_servicemanager.c +++ b/unit/unit_servicemanager/unit_servicemanager.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -157,7 +157,8 @@ typedef struct test_servicemanager { static char** test_servicemanager_list( - GBinderServiceManager* sm) + GBinderServiceManager* sm, + const GBinderIpcSyncApi* api) { TestServiceManager* self = TEST_SERVICEMANAGER(sm); @@ -169,7 +170,8 @@ GBinderRemoteObject* test_servicemanager_get_service( GBinderServiceManager* sm, const char* name, - int* status) + int* status, + const GBinderIpcSyncApi* api) { TestServiceManager* self = TEST_SERVICEMANAGER(sm); @@ -191,7 +193,8 @@ int test_servicemanager_add_service( GBinderServiceManager* sm, const char* name, - GBinderLocalObject* obj) + GBinderLocalObject* obj, + const GBinderIpcSyncApi* api) { TestServiceManager* self = TEST_SERVICEMANAGER(sm); diff --git a/unit/unit_servicename/unit_servicename.c b/unit/unit_servicename/unit_servicename.c index 4f4a035..b18c245 100644 --- a/unit/unit_servicename/unit_servicename.c +++ b/unit/unit_servicename/unit_servicename.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2019-2020 Jolla Ltd. - * Copyright (C) 2019-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2019-2021 Jolla Ltd. + * Copyright (C) 2019-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -101,7 +101,8 @@ G_DEFINE_TYPE(TestServiceManager, test_servicemanager, static char** test_servicemanager_list( - GBinderServiceManager* manager) + GBinderServiceManager* manager, + const GBinderIpcSyncApi* api) { char** ret; TestServiceManager* self = TEST_SERVICEMANAGER(manager); @@ -118,7 +119,8 @@ GBinderRemoteObject* test_servicemanager_get_service( GBinderServiceManager* manager, const char* name, - int* status) + int* status, + const GBinderIpcSyncApi* api) { *status = (-ENOENT); return NULL; @@ -129,7 +131,8 @@ int test_servicemanager_add_service( GBinderServiceManager* manager, const char* name, - GBinderLocalObject* obj) + GBinderLocalObject* obj, + const GBinderIpcSyncApi* api) { TestServiceManager* self = TEST_SERVICEMANAGER(manager); diff --git a/unit/unit_servicepoll/unit_servicepoll.c b/unit/unit_servicepoll/unit_servicepoll.c index cc2b79c..1c1af4b 100644 --- a/unit/unit_servicepoll/unit_servicepoll.c +++ b/unit/unit_servicepoll/unit_servicepoll.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018-2020 Jolla Ltd. - * Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com> + * Copyright (C) 2018-2021 Jolla Ltd. + * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com> * * You may use this file under the terms of BSD license as follows: * @@ -79,7 +79,8 @@ G_DEFINE_TYPE(TestServiceManager, test_servicemanager, static char** test_servicemanager_list( - GBinderServiceManager* manager) + GBinderServiceManager* manager, + const GBinderIpcSyncApi* api) { char** ret; TestServiceManager* self = TEST_SERVICEMANAGER(manager); @@ -96,7 +97,8 @@ GBinderRemoteObject* test_servicemanager_get_service( GBinderServiceManager* manager, const char* name, - int* status) + int* status, + const GBinderIpcSyncApi* api) { *status = (-ENOENT); return NULL; @@ -107,7 +109,8 @@ int test_servicemanager_add_service( GBinderServiceManager* manager, const char* name, - GBinderLocalObject* obj) + GBinderLocalObject* obj, + const GBinderIpcSyncApi* api) { TestServiceManager* self = TEST_SERVICEMANAGER(manager); -- GitLab