/
xioError.c
170 lines (147 loc) · 5.08 KB
/
xioError.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*********************************************************
* Copyright (C) 2010-2016 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 2.1 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*********************************************************/
/**
* @file xioError.c
*
* Handles responding to X11 I/O errors.
*/
/* Include first. Sets G_LOG_DOMAIN. */
#include "desktopEventsInt.h"
#include <sys/types.h>
#include <X11/Xlib.h>
#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <unistd.h>
#include "vmware/tools/desktopevents.h"
static int gParentPid;
static ToolsAppCtx *gCtx;
static XIOErrorHandler gOrigHandler;
/*
******************************************************************************
* DEXIOErrorHandler -- */ /**
*
* Handler for all X I/O errors. Xlib documentation says we should not
* return when handling I/O errors.
*
* @param[in] dpy Unused.
*
* @return 1 (but doesn't really return).
*
******************************************************************************
*/
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_message("Emitting %s due to X I/O error.\n", TOOLS_CORE_SIG_XIOERROR);
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;
}
/*
******************************************************************************
* XIOError_Init -- */ /**
*
* Sets up an X11 I/O error callback that stops the daemon.
*
* @param[in] ctx Application context.
* @param[in] pdata Registration data.
*
* @return TRUE.
*
******************************************************************************
*/
gboolean
XIOError_Init(ToolsAppCtx *ctx,
ToolsPluginData *pdata)
{
gCtx = ctx;
gParentPid = getpid();
gOrigHandler = XSetIOErrorHandler(DEXIOErrorHandler);
g_signal_new(TOOLS_CORE_SIG_XIOERROR,
G_OBJECT_TYPE(ctx->serviceObj),
0, // GSignalFlags
0, // class offset
NULL, // accumulator
NULL, // accu_data
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
return TRUE;
}
/*
******************************************************************************
* XIOError_Shutdown -- */ /**
*
* Shutdown function, restores the original X I/O error handler.
*
* @param[in] ctx Application context.
* @param[in] pdata Plugin data (unused).
*
******************************************************************************
*/
void
XIOError_Shutdown(ToolsAppCtx *ctx,
ToolsPluginData *pdata)
{
XSetIOErrorHandler(gOrigHandler);
gCtx = NULL;
gOrigHandler = NULL;
}