Skip to content

Commit

Permalink
Un*x session management integration via desktopEvents
Browse files Browse the repository at this point in the history
So we have this guest agent, vmusr, which runs in the context of graphical
desktop sessions.  It's intended to run for the duration of the session,
which is normally fine, but it has a nasty habit of overstaying its
welcome.  Our gracious host, the session manager, politely asks its guests
to leave, but vmusr just doesn't wanna listen.

Rather than stick around until the X server terminates, this change
introduces integration with XSM-compliant[1] session managers such
that, in response to a heads-up from the manager, we can exit cleanly.

libSM and libICE are used to get the job done.

libICE clients use their own connections, and they're managed via a
custom GSource.  For now, this desktopEvents feature is the only libICE
client, so rather than go overboard and deal with ICE in a separate
provider plugin, all ICE-GLib connection management is handled here.

Additionally, I changed up the Desktop Events features' mini API to
keep a GHashTable as the plugin's private data.  Each mini feature may
add its own private data to that hash using the feature's name as a
key.

1.  http://cgit.freedesktop.org/xorg/lib/libSM/tree/doc/SMlib.xml

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
  • Loading branch information
VMware, Inc authored and Marcelo Vanzin committed Mar 29, 2011
1 parent 2e7bbe3 commit cfa1982
Show file tree
Hide file tree
Showing 8 changed files with 535 additions and 12 deletions.
21 changes: 21 additions & 0 deletions open-vm-tools/configure.ac
Expand Up @@ -500,6 +500,21 @@ else
[libXtst not found. Please configure without X11 (using --without-x) or install the libXtst devel package(s).])],
[$COMMON_XLIBS])

AC_CHECK_LIB(
[SM],
[SmcOpenConnection],
[XSM_LIBS="-lSM -lICE" && have_xsm_lib="yes"],
[]
[-lICE])

AC_CHECK_HEADERS([X11/SM/SMlib.h X11/ICE/ICElib.h],
[have_xsm_header="yes"],
[],
[])
if test "$have_xsm_lib" = "yes" -a "$have_xsm_header" = "yes"; then
have_xsm="yes"
fi

# If we're building with support for Unity, we'll need a few additional
# libraries.
if test "$enable_unity" != "no"; then
Expand Down Expand Up @@ -1070,6 +1085,7 @@ AM_CONDITIONAL(THIRTY_TWO_BIT_USERSPACE, test "$userSpaceBitness" = "32")
AM_CONDITIONAL(HAVE_X11, test "$have_x" = "yes")
AM_CONDITIONAL(HAVE_ICU, test "$with_icu" = "yes")
AM_CONDITIONAL(WITH_KERNEL_MODULES, test "$with_kernel_modules" = "yes")
AM_CONDITIONAL(HAVE_XSM, test "$have_xsm" = "yes")
AM_CONDITIONAL(ENABLE_UNITY, test "$enable_unity" = "yes")
AM_CONDITIONAL(ENABLE_TESTS, test "$have_cunit" = "yes")
AM_CONDITIONAL(WITH_ROOT_PRIVILEGES, test "$with_root_privileges" = "yes")
Expand All @@ -1081,6 +1097,10 @@ AM_CONDITIONAL(HAVE_GTKMM, test "$have_x" = "yes" -a "$with_gtkmm" = "yes")
AM_CONDITIONAL(HAVE_PAM, test "$with_pam" = "yes")
AM_CONDITIONAL(USE_SLASH_PROC, test "os" = "linux" -a "$have_glib_2_14" = "yes")

if test "$have_xsm" != "yes"; then
AC_DEFINE([NO_XSM], 1, [])
fi

### Feature-specific flags / actions
# Combine where possible

Expand Down Expand Up @@ -1141,6 +1161,7 @@ AC_SUBST([MODULES_OS])
AC_SUBST([MODULES_DIR])
AC_SUBST([MODULES])
AC_SUBST([COMMON_XLIBS])
AC_SUBST([XSM_LIBS])
AC_SUBST([PAM_PREFIX])
AC_SUBST([PLUGIN_CPPFLAGS])
AC_SUBST([PLUGIN_LDFLAGS])
Expand Down
4 changes: 4 additions & 0 deletions open-vm-tools/services/plugins/desktopEvents/Makefile.am
Expand Up @@ -36,3 +36,7 @@ libdesktopEvents_la_SOURCES += reload.c
libdesktopEvents_la_SOURCES += x11Lock.c
libdesktopEvents_la_SOURCES += xioError.c

if HAVE_XSM
libdesktopEvents_la_LIBADD += @XSM_LIBS@
libdesktopEvents_la_SOURCES += sessionMgr.c
endif
20 changes: 18 additions & 2 deletions open-vm-tools/services/plugins/desktopEvents/deFeatures.h
Expand Up @@ -36,7 +36,18 @@ Reload_Init(ToolsAppCtx *ctx,
ToolsPluginData *pdata);

void
Reload_Shutdown(ToolsAppCtx *ctx);
Reload_Shutdown(ToolsAppCtx *ctx,
ToolsPluginData *pdata);

#ifndef NO_XSM
gboolean
SessionMgr_Init(ToolsAppCtx *ctx,
ToolsPluginData *pdata);

void
SessionMgr_Shutdown(ToolsAppCtx *ctx,
ToolsPluginData *pdata);
#endif

gboolean
X11Lock_Init(ToolsAppCtx *ctx,
Expand All @@ -47,16 +58,21 @@ XIOError_Init(ToolsAppCtx *ctx,
ToolsPluginData *pdata);

void
XIOError_Shutdown(ToolsAppCtx *ctx);
XIOError_Shutdown(ToolsAppCtx *ctx,
ToolsPluginData *pdata);


#if defined(DE_MAIN)
static DesktopEventFuncs gFeatures[] = {
{ X11Lock_Init, NULL, FALSE },
{ Reload_Init, Reload_Shutdown, FALSE },
#ifndef NO_XSM
{ SessionMgr_Init, SessionMgr_Shutdown, FALSE },
#endif
{ XIOError_Init, XIOError_Shutdown, FALSE },
};
#endif


#endif /* _DEFEATURES_H_ */

23 changes: 17 additions & 6 deletions open-vm-tools/services/plugins/desktopEvents/desktopEvents.c
Expand Up @@ -39,27 +39,35 @@
*
* Calls the shutdown function of the available features.
*
* @param[in] obj Unused.
* @param[in] ctx The application context.
* @param[in] plugin Unused.
* @param[in] plugin Plugin data.
*
* @return TRUE.
*
******************************************************************************
*/

static gboolean
DesktopEventsShutdown(ToolsAppCtx *ctx,
DesktopEventsShutdown(gpointer serviceObj,
ToolsAppCtx *ctx,
ToolsPluginData *plugin)
{
size_t i;

for (i = 0; i < ARRAYSIZE(gFeatures); i++) {
DesktopEventFuncs *f = &gFeatures[i];
if (f->initialized && f->shutdownFn != NULL) {
f->shutdownFn(ctx);
f->shutdownFn(ctx, plugin);
}
}

if (plugin->_private) {
g_hash_table_remove(plugin->_private, DE_PRIVATE_CTX);
g_hash_table_unref(plugin->_private);
plugin->_private = NULL;
}

return TRUE;
}

Expand All @@ -83,6 +91,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
static ToolsPluginData regData = {
"desktopEvents",
NULL,
NULL,
NULL
};

Expand All @@ -93,6 +102,9 @@ ToolsOnLoad(ToolsAppCtx *ctx)
#endif

regData.regs = g_array_new(FALSE, TRUE, sizeof (ToolsAppReg));
regData._private = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(regData._private, DE_PRIVATE_CTX, ctx);

for (i = 0; i < ARRAYSIZE(gFeatures); i++) {
DesktopEventFuncs *f = &gFeatures[i];
if (!f->initFn(ctx, &regData)) {
Expand All @@ -107,7 +119,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
*/
if (i == ARRAYSIZE(gFeatures)) {
ToolsPluginSignalCb sigs[] = {
{ TOOLS_CORE_SIG_SHUTDOWN, DesktopEventsShutdown, NULL }
{ TOOLS_CORE_SIG_SHUTDOWN, DesktopEventsShutdown, &regData }
};
ToolsAppReg regs[] = {
{ TOOLS_APP_SIGNALS, VMTools_WrapArray(sigs, sizeof *sigs, ARRAYSIZE(sigs)) },
Expand All @@ -117,7 +129,7 @@ ToolsOnLoad(ToolsAppCtx *ctx)
}

/* Failed to initialize something, clean up and unload. */
DesktopEventsShutdown(ctx, &regData);
DesktopEventsShutdown(NULL, ctx, &regData);

/* Cleanup regData to make sure memory is freed. */
for (i = 0; i < regData.regs->len; i++) {
Expand All @@ -130,4 +142,3 @@ ToolsOnLoad(ToolsAppCtx *ctx)

return NULL;
}

12 changes: 10 additions & 2 deletions open-vm-tools/services/plugins/desktopEvents/desktopEventsInt.h
Expand Up @@ -31,15 +31,23 @@

typedef struct DesktopEventFuncs {
gboolean (*initFn)(ToolsAppCtx *, ToolsPluginData *);
void (*shutdownFn)(ToolsAppCtx *ctx);
void (*shutdownFn)(ToolsAppCtx *ctx, ToolsPluginData *);
gboolean initialized;
} DesktopEventFuncs;


/*
* This plugin's private data field is a GHashTable*. Each sub-feature may use
* that table to keep its own private state. The following key is reserved and
* points to the hosting application's ToolsAppCtx.
*/
#define DE_PRIVATE_CTX "ctx"


/*
* This platform-specific file defines the list of features available
* for the current platform being built.
*/
#include "deFeatures.h"

#endif /* _DESKTOPEVENTSINT_H_ */

4 changes: 3 additions & 1 deletion open-vm-tools/services/plugins/desktopEvents/reload.c
Expand Up @@ -111,12 +111,14 @@ Reload_Init(ToolsAppCtx *ctx,
* Unregisters the SIGUSR2 signal handler.
*
* @param[in] ctx Application context.
* @param[in] pdata Plugin data (unused).
*
******************************************************************************
*/

void
Reload_Shutdown(ToolsAppCtx *ctx)
Reload_Shutdown(ToolsAppCtx *ctx,
ToolsPluginData *pdata)
{
g_source_destroy(gReloadSrc);
g_source_unref(gReloadSrc);
Expand Down

0 comments on commit cfa1982

Please sign in to comment.