Skip to content

Commit

Permalink
Running gRPC Server independently (#158)
Browse files Browse the repository at this point in the history
The loading/unloading behavior of the Vulkan/OpenXR Dive layer library varies significantly across Android applications.
For example for Vulkan apps it loads - unloads - reloads the library during execution. For an Unity-based OpenXR
app that creates two instances, the behavior is the same.

The gRPC Server starts when the library loads for the first time. Then, a function prevents the library from being unloaded.
This keeps both the library and server loaded exactly once, even if apps try to reload or close them.
In this way, the Server lives for the entire lifecycle of the app.
  • Loading branch information
elviscapiaq authored Jan 30, 2025
1 parent 9fe68b2 commit b4f8b82
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 22 deletions.
5 changes: 3 additions & 2 deletions capture_service/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ limitations under the License.

#include "server.h"

int main(int argc, char **argv) {
Dive::server_main();
int main(int argc, char **argv)
{
Dive::ServerMain();
return 0;
}
5 changes: 3 additions & 2 deletions capture_service/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ limitations under the License.

namespace Dive
{
int server_main();
}
int ServerMain();
void StopServer();
} // namespace Dive
23 changes: 21 additions & 2 deletions capture_service/service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,26 @@ grpc::Status DiveServiceImpl::DownloadFile(grpc::ServerContext *cont
return grpc::Status::OK;
}

std::unique_ptr<grpc::Server> &GetServer()
{
static std::unique_ptr<grpc::Server> server = nullptr;
return server;
}

void StopServer()
{
auto &server = GetServer();
if (server)
{
LOGI("StopServer at service.cc");
server->Shutdown();
server = nullptr;
}
}

void RunServer(uint16_t port)
{
LOGI("port is %d\n", port);
std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
DiveServiceImpl service;

Expand All @@ -142,12 +160,13 @@ void RunServer(uint16_t port)
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());

builder.RegisterService(&service);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
auto &server = GetServer();
server = builder.BuildAndStart();
LOGI("Server listening on %s", server_address.c_str());
server->Wait();
}

int server_main()
int ServerMain()
{
RunServer(absl::GetFlag(FLAGS_port));
return 0;
Expand Down
48 changes: 46 additions & 2 deletions layer/layer_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

#ifdef _WIN32
# include <windows.h>
#else
# include <dlfcn.h>
#endif

#include "layer_common.h"

#include <cstdio>
Expand Down Expand Up @@ -58,14 +64,15 @@ ServerRunner::ServerRunner()
LOGI("libwrap loaded: %d", is_libwrap_loaded);
if (is_libwrap_loaded)
{
server_thread = std::thread(Dive::server_main);
server_thread = std::thread(Dive::ServerMain);
}
}

ServerRunner::~ServerRunner()
{
if (is_libwrap_loaded && server_thread.joinable())
{
Dive::StopServer();
LOGI("Wait for server thread to join");
server_thread.join();
}
Expand All @@ -77,4 +84,41 @@ ServerRunner &GetServerRunner()
return runner;
}

} // namespace DiveLayer
} // namespace DiveLayer

void PreventLibraryUnload()
{
#ifdef _WIN32
HMODULE module = nullptr;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
reinterpret_cast<LPCSTR>(&PreventLibraryUnload),
&module);
#else
Dl_info info;
if (dladdr(reinterpret_cast<void *>(&PreventLibraryUnload), &info))
{
dlopen(info.dli_fname, RTLD_NOW | RTLD_NOLOAD | RTLD_LOCAL | RTLD_NODELETE);
}
#endif
}

#ifdef _WIN32
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
[[maybe_unused]] auto &server = DiveLayer::GetServerRunner();
PreventLibraryUnload();
}
return TRUE;
}
#else
extern "C"
{
__attribute__((constructor)) void InitializeLibrary()
{
[[maybe_unused]] auto &server = DiveLayer::GetServerRunner();
PreventLibraryUnload();
}
}
#endif
9 changes: 1 addition & 8 deletions layer/openxr_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,6 @@ struct XrSessionData
{
XrSession session;
XrGeneratedDispatchTable dispatch_table;
ServerRunner &server;

XrSessionData() :
server(GetServerRunner())
{
}
};

static thread_local XrInstanceData *last_used_xr_instance_data = nullptr;
Expand Down Expand Up @@ -190,8 +184,7 @@ XRAPI_ATTR XrResult XRAPI_CALL ApiDiveLayerXrDestroyInstance(XrInstance instance

LOGD("ApiDiveLayerXrDestroyInstance\n");
XrResult result = XR_SUCCESS;

auto sess_data = GetXrInstanceLayerData(DataKey(instance));
auto sess_data = GetXrInstanceLayerData(DataKey(instance));
if (sess_data)
{
result = sess_data->dispatch_table.DestroyInstance(instance);
Expand Down
6 changes: 0 additions & 6 deletions layer/vk_layer_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ struct InstanceData
{
VkInstance instance;
InstanceDispatchTable dispatch_table;
ServerRunner &server;

InstanceData() :
server(GetServerRunner())
{
}
};

struct DeviceData
Expand Down

0 comments on commit b4f8b82

Please sign in to comment.