diff --git a/hw/dmx/dmxscrinit.c b/hw/dmx/dmxscrinit.c index 48e5fa8ce..44e58b4e8 100644 --- a/hw/dmx/dmxscrinit.c +++ b/hw/dmx/dmxscrinit.c @@ -745,13 +745,6 @@ dmxScreenEventCheckIgnore (ScreenPtr pScreen, return FALSE; } -static Bool -dmxScreenReplyCheckIgnore (ScreenPtr pScreen, - xcb_generic_reply_t *reply) -{ - return FALSE; -} - static void dmxScreenCheckForIOError (ScreenPtr pScreen) { @@ -781,7 +774,8 @@ dmxBEDispatch (ScreenPtr pScreen) { DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; xcb_generic_event_t *event; - xcb_generic_reply_t *reply; + xcb_generic_error_t *error; + void *reply; dmxScreen->inDispatch = TRUE; @@ -807,28 +801,32 @@ dmxBEDispatch (ScreenPtr pScreen) while (dmxScreen->request.head && xcb_poll_for_reply (dmxScreen->connection, dmxScreen->request.head->sequence, - (void *) &reply, - NULL)) + (void **) &reply, + &error)) { - DMXSequence *head = dmxScreen->request.head; + static xcb_generic_reply_t _default_rep = { 1 }; + DMXSequence *head = dmxScreen->request.head; + xcb_generic_reply_t *rep = &_default_rep; + if (error) + rep = (xcb_generic_reply_t *) error; if (reply) - { - if (!dmxScreenReplyCheckSync (pScreen, reply) && - !dmxScreenReplyCheckIgnore (pScreen, reply)) - { - dmxLogOutput (dmxScreen, - "unhandled reply sequence %d\n", - reply->sequence); - } + rep = (xcb_generic_reply_t *) reply; - free (reply); - } - else + if (!dmxScreenReplyCheckSync (pScreen, head->sequence, rep)) { - dmxLogOutput (dmxScreen, "error sequence %d\n", head->sequence); + /* error response */ + if (rep->response_type == 0) + dmxLogOutput (dmxScreen, "error %d sequence %d\n", + ((xcb_generic_error_t *) rep)->error_code, + head->sequence); } + if (reply) + free (reply); + if (error) + free (error); + dmxScreen->request.head = head->next; if (!dmxScreen->request.head) dmxScreen->request.tail = &dmxScreen->request.head; diff --git a/hw/dmx/dmxsync.c b/hw/dmx/dmxsync.c index 08cf15c49..1b1e24c1e 100644 --- a/hw/dmx/dmxsync.c +++ b/hw/dmx/dmxsync.c @@ -63,20 +63,73 @@ static OsTimerPtr dmxSyncTimer; static int dmxSyncPending = 0; static int dmxSyncRequest = 0; +/* dispatch all pending back-end server responses */ +void +dmxDispatch (void) +{ + int i; + + for (i = 0; i < dmxNumScreens; i++) + if (dmxScreens[i].alive) + dmxBEDispatch (screenInfo.screens[i]); +} + +/* non-blocking wait for back-end server response. returns 0 when no + more reponses can arrive */ +int +dmxWaitForResponse (void) +{ + fd_set rfds; + int nfd = 0; + int i, ret = 0; + + FD_ZERO (&rfds); + + for (i = 0; i < dmxNumScreens; i++) + { + if (dmxScreens[i].beDisplay && dmxScreens[i].alive) + { + xcb_flush (dmxScreens[i].connection); + + if (xcb_connection_has_error (dmxScreens[i].connection)) + { + dmxScreens[i].alive = FALSE; + ret = -1; + } + else + { + FD_SET (dmxScreens[i].fd, &rfds); + + if (dmxScreens[i].fd > nfd) + nfd = dmxScreens[i].fd; + } + } + } + + if (ret == 0 && nfd) + { + do { + ret = select (nfd + 1, &rfds, 0, 0, 0); + } while (ret == -1 && errno == EINTR); + + /* screens with broken connections are detached in the + block handler */ + } + + return nfd; +} + static void dmxDoSync(DMXScreenInfo *dmxScreen) { dmxScreen->needsSync = FALSE; - if (!dmxScreen->beDisplay) - { - dmxScreen->sync.sequence = 0; + if (!dmxScreen->alive) return; /* FIXME: Is this correct behavior for sync stats? */ - } if (dmxScreen->sync.sequence) return; - dmxScreen->sync = xcb_get_input_focus_unchecked (dmxScreen->connection); + dmxScreen->sync = xcb_get_input_focus (dmxScreen->connection); dmxAddSequence (&dmxScreen->request, dmxScreen->sync.sequence); dmxSyncRequest++; } @@ -85,54 +138,26 @@ static CARD32 dmxSyncCallback(OsTimerPtr timer, CARD32 time, pointer arg) { int i; - while (dmxSyncRequest) + /* make sure TimerFree is not called from while waiting for + pending replies */ + dmxSyncTimer = NULL; + + while (dmxSyncRequest && dmxWaitForResponse ()) { - fd_set rfds; - int ret, fd = 0; + dmxDispatch (); - /* timer expired and there is pending sync replies that need - to be waited for before we can allow further processing - of client requests */ - - FD_ZERO (&rfds); - for (i = 0; i < dmxNumScreens; i++) { - if (dmxScreens[i].beDisplay) + if (!dmxScreens[i].alive) { - xcb_flush (dmxScreens[i].connection); - if (xcb_connection_has_error (dmxScreens[i].connection)) + /* remove pending replies from disconnected screens */ + if (dmxScreens[i].sync.sequence) { - if (dmxScreens[i].sync.sequence) - { - dmxScreens[i].sync.sequence = 0; - dmxSyncRequest--; - } - } - else - { - FD_SET (dmxScreens[i].fd, &rfds); - - if (dmxScreens[i].fd > fd) - fd = dmxScreens[i].fd; + dmxScreens[i].sync.sequence = 0; + dmxSyncRequest--; } } } - - if (fd) - { - do { - ret = select (fd + 1, &rfds, 0, 0, 0); - } while (ret == -1 && errno == EINTR); - } - - dmxSyncPending++; - - for (i = 0; i < dmxNumScreens; i++) - if (dmxScreens[i].beDisplay) - dmxBEDispatch (screenInfo.screens[i]); - - dmxSyncPending--; } if (dmxSyncPending) @@ -144,11 +169,12 @@ static CARD32 dmxSyncCallback(OsTimerPtr timer, CARD32 time, pointer arg) dmxSyncPending = 0; if (dmxSyncRequest) + { + dmxSyncTimer = timer; return dmxSyncInterval; + } } - dmxSyncTimer = NULL; - return 0; /* Do not place on queue again */ } @@ -246,8 +272,11 @@ void dmxSync(DMXScreenInfo *dmxScreen, Bool now) } else if (!dmxSyncTimer) { - dmxSyncTimer = TimerSet(dmxSyncTimer, 0, dmxSyncInterval, - dmxSyncCallback, NULL); + dmxSyncTimer = TimerSet (dmxSyncTimer, + 0, + dmxSyncInterval, + dmxSyncCallback, + NULL); } } else @@ -257,19 +286,22 @@ void dmxSync(DMXScreenInfo *dmxScreen, Bool now) * up-to-date. */ if (dmxScreen) { - dmxDoSync(dmxScreen); - dmxSyncCallback(NULL, 0, NULL); + dmxDoSync (dmxScreen); + dmxSyncCallback (NULL, 0, NULL); } } } +/* error or reply doesn't matter, all we need is some response + from the back-end server */ Bool dmxScreenReplyCheckSync (ScreenPtr pScreen, + unsigned int sequence, xcb_generic_reply_t *reply) { DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - if (reply->sequence != dmxScreen->sync.sequence) + if (sequence != dmxScreen->sync.sequence) return FALSE; dmxScreen->sync.sequence = 0; @@ -277,7 +309,7 @@ dmxScreenReplyCheckSync (ScreenPtr pScreen, dmxSyncRequest--; if (dmxSyncRequest == 0) { - if (dmxSyncPending == 0) + if (dmxSyncPending == 0 && dmxSyncTimer) { TimerFree (dmxSyncTimer); dmxSyncTimer = NULL; @@ -286,4 +318,3 @@ dmxScreenReplyCheckSync (ScreenPtr pScreen, return TRUE; } - diff --git a/hw/dmx/dmxsync.h b/hw/dmx/dmxsync.h index e7575d558..c2dcaf9ff 100644 --- a/hw/dmx/dmxsync.h +++ b/hw/dmx/dmxsync.h @@ -37,9 +37,12 @@ #ifndef _DMXSYNC_H_ #define _DMXSYNC_H_ +extern void dmxDispatch (void); +extern int dmxWaitForResponse (void); extern void dmxSyncActivate(const char *interval); extern void dmxSyncInit(void); extern void dmxSync(DMXScreenInfo *dmxScreen, Bool now); extern Bool dmxScreenReplyCheckSync (ScreenPtr pScreen, + unsigned int sequence, xcb_generic_reply_t *reply); #endif