Ungrab the server before parsing the config

This moves the loading of the rc.lua and managing of pre-existing clients to
after we ungrab the server during startup. To make sure we have no races with
clients which start up parallel to awesome, we do the QueryTree for all the
clients that we have to manage before the ungrab, but start managing the clients
only after the ungrab.

This means that we have already selected our event mask on the root window in
scan() and thus received an UnmapNotify event when we reparent windows into a
frame window. This has the effect that we immediately unmanage the client again,
whoops.

To fix this, we grab the server again and remove our event mask on the root
window again while we reparent.

This should hopefully fix all cases where we deadlock during startup because
pulseaudio wants to talk to the X server, but is being ignored because we have
the server grabbed while at the same time we are waiting for pulseaudio.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2011-10-19 15:11:11 +02:00
parent 1801a8be46
commit bf76b3842b
2 changed files with 41 additions and 16 deletions

View File

@ -80,20 +80,15 @@ awesome_atexit(bool restart)
/** Scan X to find windows to manage. /** Scan X to find windows to manage.
*/ */
static void static void
scan(void) scan(xcb_query_tree_cookie_t tree_c)
{ {
int i, tree_c_len; int i, tree_c_len;
xcb_query_tree_cookie_t tree_c;
xcb_query_tree_reply_t *tree_r; xcb_query_tree_reply_t *tree_r;
xcb_window_t *wins = NULL; xcb_window_t *wins = NULL;
xcb_get_window_attributes_reply_t *attr_r; xcb_get_window_attributes_reply_t *attr_r;
xcb_get_geometry_reply_t *geom_r; xcb_get_geometry_reply_t *geom_r;
long state; long state;
/* Get the window tree associated to this screen */
tree_c = xcb_query_tree_unchecked(globalconf.connection,
globalconf.screen->root);
tree_r = xcb_query_tree_reply(globalconf.connection, tree_r = xcb_query_tree_reply(globalconf.connection,
tree_c, tree_c,
NULL); NULL);
@ -321,6 +316,7 @@ main(int argc, char **argv)
xdgHandle xdg; xdgHandle xdg;
bool no_argb = false; bool no_argb = false;
xcb_generic_event_t *event; xcb_generic_event_t *event;
xcb_query_tree_cookie_t tree_c;
static struct option long_options[] = static struct option long_options[] =
{ {
{ "help", 0, NULL, 'h' }, { "help", 0, NULL, 'h' },
@ -541,6 +537,18 @@ main(int argc, char **argv)
(const uint32_t[]) { globalconf.screen->black_pixel, globalconf.screen->white_pixel }); (const uint32_t[]) { globalconf.screen->black_pixel, globalconf.screen->white_pixel });
xcb_destroy_window(globalconf.connection, tmp_win); xcb_destroy_window(globalconf.connection, tmp_win);
/* Get the window tree associated to this screen */
tree_c = xcb_query_tree_unchecked(globalconf.connection,
globalconf.screen->root);
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
ROOT_WINDOW_EVENT_MASK);
/* we will receive events, stop grabbing server */
xcb_ungrab_server(globalconf.connection);
/* Parse and run configuration file */ /* Parse and run configuration file */
if (!luaA_parserc(&xdg, confpath, true)) if (!luaA_parserc(&xdg, confpath, true))
fatal("couldn't find any rc file"); fatal("couldn't find any rc file");
@ -550,17 +558,8 @@ main(int argc, char **argv)
xdgWipeHandle(&xdg); xdgWipeHandle(&xdg);
/* scan existing windows */ /* scan existing windows */
scan(); scan(tree_c);
{
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
ROOT_WINDOW_EVENT_MASK);
}
/* we will receive events, stop grabbing server */
xcb_ungrab_server(globalconf.connection);
xcb_flush(globalconf.connection); xcb_flush(globalconf.connection);
/* main event loop */ /* main event loop */

View File

@ -433,9 +433,35 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, bool startup)
FRAME_SELECT_INPUT_EVENT_MASK, FRAME_SELECT_INPUT_EVENT_MASK,
globalconf.default_cmap globalconf.default_cmap
}); });
if (startup)
{
/* The client is already mapped, thus we must be sure that we don't send
* ourselves an UnmapNotify due to the xcb_reparent_window().
*
* Grab the server to make sure we don't lose any events.
*/
uint32_t no_event[] = { 0 };
xcb_grab_server(globalconf.connection);
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
no_event);
}
xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0); xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0);
xcb_map_window(globalconf.connection, w); xcb_map_window(globalconf.connection, w);
if (startup)
{
xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root,
XCB_CW_EVENT_MASK,
ROOT_WINDOW_EVENT_MASK);
xcb_ungrab_server(globalconf.connection);
}
/* Do this now so that we don't get any events for the above /* Do this now so that we don't get any events for the above
* (Else, reparent could cause an UnmapNotify) */ * (Else, reparent could cause an UnmapNotify) */
xcb_change_window_attributes(globalconf.connection, w, XCB_CW_EVENT_MASK, select_input_val); xcb_change_window_attributes(globalconf.connection, w, XCB_CW_EVENT_MASK, select_input_val);