Stop handling file descriptor events after a port reset.

If the port resets itself after detecting a fault, then the polling events
for that port are no longer valid. This patch fixes a latent bug that
would appear if a fault and another event were to happen simultaneously.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2013-02-01 05:19:12 +01:00
parent da594e78d9
commit 0dbdd9c2cd
3 changed files with 10 additions and 7 deletions

View File

@ -692,7 +692,7 @@ struct PortIdentity clock_parent_identity(struct clock *c)
int clock_poll(struct clock *c) int clock_poll(struct clock *c)
{ {
int cnt, i, j, k, lost = 0, sde = 0; int cnt, err, i, j, k, lost = 0, sde = 0;
enum fsm_event event; enum fsm_event event;
cnt = poll(c->pollfd, ARRAY_SIZE(c->pollfd), -1); cnt = poll(c->pollfd, ARRAY_SIZE(c->pollfd), -1);
@ -710,7 +710,7 @@ int clock_poll(struct clock *c)
for (i = 0; i < c->nports; i++) { for (i = 0; i < c->nports; i++) {
/* Let the ports handle their events. */ /* Let the ports handle their events. */
for (j = 0; j < N_POLLFD; j++) { for (j = err = 0; j < N_POLLFD && !err; j++) {
k = N_CLOCK_PFD * i + j; k = N_CLOCK_PFD * i + j;
if (c->pollfd[k].revents & (POLLIN|POLLPRI)) { if (c->pollfd[k].revents & (POLLIN|POLLPRI)) {
event = port_event(c->port[i], j); event = port_event(c->port[i], j);
@ -718,7 +718,7 @@ int clock_poll(struct clock *c)
sde = 1; sde = 1;
if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event) if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event)
lost = 1; lost = 1;
port_dispatch(c->port[i], event, 0); err = port_dispatch(c->port[i], event, 0);
/* Clear any fault after a little while. */ /* Clear any fault after a little while. */
if (PS_FAULTY == port_state(c->port[i])) { if (PS_FAULTY == port_state(c->port[i])) {
clock_fault_timeout(c, i, 1); clock_fault_timeout(c, i, 1);

7
port.c
View File

@ -1406,7 +1406,7 @@ struct foreign_clock *port_compute_best(struct port *p)
return p->best; return p->best;
} }
void port_dispatch(struct port *p, enum fsm_event event, int mdiff) int port_dispatch(struct port *p, enum fsm_event event, int mdiff)
{ {
enum port_state next; enum port_state next;
@ -1432,11 +1432,11 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
next = port_initialize(p) ? PS_FAULTY : PS_LISTENING; next = port_initialize(p) ? PS_FAULTY : PS_LISTENING;
port_show_transition(p, next, event); port_show_transition(p, next, event);
p->state = next; p->state = next;
return; return 1;
} }
if (next == p->state) if (next == p->state)
return; return 0;
port_show_transition(p, next, event); port_show_transition(p, next, event);
@ -1493,6 +1493,7 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
}; };
} }
p->state = next; p->state = next;
return 0;
} }
enum fsm_event port_event(struct port *p, int fd_index) enum fsm_event port_event(struct port *p, int fd_index)

4
port.h
View File

@ -68,8 +68,10 @@ struct foreign_clock *port_compute_best(struct port *port);
* @param port A pointer previously obtained via port_open(). * @param port A pointer previously obtained via port_open().
* @param event One of the @a fsm_event codes. * @param event One of the @a fsm_event codes.
* @param mdiff Whether a new master has been selected. * @param mdiff Whether a new master has been selected.
* @return Zero if the port's file descriptor array is still valid,
* and non-zero if it has become invalid.
*/ */
void port_dispatch(struct port *p, enum fsm_event event, int mdiff); int port_dispatch(struct port *p, enum fsm_event event, int mdiff);
/** /**
* Generates state machine events based on activity on a port's file * Generates state machine events based on activity on a port's file