static void ToolsCoreCleanup(ToolsServiceState *state) { ToolsCorePool_Shutdown(&state->ctx); ToolsCore_UnloadPlugins(state); if (state->ctx.rpc != NULL) { RpcChannel_Stop(state->ctx.rpc); RpcChannel_Destroy(state->ctx.rpc); state->ctx.rpc = NULL; } g_key_file_free(state->ctx.config); g_main_loop_unref(state->ctx.mainLoop); #if defined(G_PLATFORM_WIN32) if (state->ctx.comInitialized) { CoUninitialize(); state->ctx.comInitialized = FALSE; } #endif #if !defined(_WIN32) if (state->ctx.envp) { System_FreeNativeEnviron(state->ctx.envp); state->ctx.envp = NULL; } #endif g_object_set(state->ctx.serviceObj, TOOLS_CORE_PROP_CTX, NULL, NULL); g_object_unref(state->ctx.serviceObj); state->ctx.serviceObj = NULL; state->ctx.config = NULL; state->ctx.mainLoop = NULL; }
static gboolean ReloadSelf(const siginfo_t *info, gpointer data) { ToolsAppCtx *ctx = data; if (ctx->rpc != NULL) { RpcChannel_Stop(ctx->rpc); } Reload_Do(); return FALSE; }
static int DEXIOErrorHandler(Display *dpy) { pid_t my_pid = getpid(); /* * ProcMgr_ExecAsync() needs to fork off a child to handle watching the * process being run. When it dies, it will come through here, so we don't * want to let it shut down the RPC channel. */ if (my_pid == gParentPid) { g_debug("%s", __func__); /* * Inform clients capable of/interested in quick'n'dirty cleanup upon an * X I/O error. */ g_signal_emit_by_name(gCtx->serviceObj, TOOLS_CORE_SIG_XIOERROR, gCtx); /* * XXX: the really correct thing to do here would be to properly stop all * plugins so that capabilities are unset and all other "clean shutdown" * tasks are performed. Unfortunately two things currently prevent that: * * . we can't rely on g_main_loop_quit() because we can't return from this * function (well, we can, but Xlib will exit() before vmtoolsd is able * to clean up things), so the main loop will never regain control off * the app. * * . we can't access the internal vmtoolsd functions that cleanly shuts * down plugins. * * So, right now, let's stick with just stopping the RPC channel so that * the host is notified the application is gone. This may cause temporary * issues with clients that only look at capabilities and not at the * status of vmusr. */ if (gCtx->rpc != NULL) { RpcChannel_Stop(gCtx->rpc); } exit(EXIT_FAILURE); } else { /* * _exit is used here so that any atexit() registered routines don't * interfere with any resources shared with the parent. */ g_debug("%s hit from forked() child", __func__); _exit(EXIT_FAILURE); } return 1; }
gboolean RpcChannel_SendOneRaw(const char *data, size_t dataLen, char **result, size_t *resultLen) { RpcChannel *chan; gboolean status; status = FALSE; chan = RpcChannel_New(); if (chan == NULL) { if (result != NULL) { *result = Util_SafeStrdup("RpcChannel: Unable to create " "the RpcChannel object"); if (resultLen != NULL) { *resultLen = strlen(*result); } } goto sent; } else if (!RpcChannel_Start(chan)) { if (result != NULL) { *result = Util_SafeStrdup("RpcChannel: Unable to open the " "communication channel"); if (resultLen != NULL) { *resultLen = strlen(*result); } } goto sent; } else if (!RpcChannel_Send(chan, data, dataLen, result, resultLen)) { /* We already have the description of the error */ goto sent; } status = TRUE; sent: Debug(LGPFX "Request %s: reqlen=%"FMTSZ"u, replyLen=%"FMTSZ"u\n", status ? "OK" : "FAILED", dataLen, resultLen ? *resultLen : 0); if (chan) { RpcChannel_Stop(chan); RpcChannel_Destroy(chan); } return status; }
static gboolean RpcChannelRestart(gpointer _chan) { RpcChannelInt *chan = _chan; RpcChannel_Stop(&chan->impl); if (!RpcChannel_Start(&chan->impl)) { Warning("Channel restart failed [%d]\n", chan->rpcErrorCount); if (chan->resetCb != NULL) { chan->resetCb(&chan->impl, FALSE, chan->resetData); } } else { chan->rpcError = FALSE; } return FALSE; }