Skip to content

Commit

Permalink
Stop handling file descriptor events after a port reset.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
richardcochran committed Feb 3, 2013
1 parent da594e7 commit 0dbdd9c
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 7 deletions.
6 changes: 3 additions & 3 deletions clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ struct PortIdentity clock_parent_identity(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;

cnt = poll(c->pollfd, ARRAY_SIZE(c->pollfd), -1);
Expand All @@ -710,15 +710,15 @@ int clock_poll(struct clock *c)
for (i = 0; i < c->nports; i++) {

/* 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;
if (c->pollfd[k].revents & (POLLIN|POLLPRI)) {
event = port_event(c->port[i], j);
if (EV_STATE_DECISION_EVENT == event)
sde = 1;
if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event)
lost = 1;
port_dispatch(c->port[i], event, 0);
err = port_dispatch(c->port[i], event, 0);
/* Clear any fault after a little while. */
if (PS_FAULTY == port_state(c->port[i])) {
clock_fault_timeout(c, i, 1);
Expand Down
7 changes: 4 additions & 3 deletions port.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ struct foreign_clock *port_compute_best(struct port *p)
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;

Expand All @@ -1432,11 +1432,11 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
next = port_initialize(p) ? PS_FAULTY : PS_LISTENING;
port_show_transition(p, next, event);
p->state = next;
return;
return 1;
}

if (next == p->state)
return;
return 0;

port_show_transition(p, next, event);

Expand Down Expand Up @@ -1493,6 +1493,7 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
};
}
p->state = next;
return 0;
}

enum fsm_event port_event(struct port *p, int fd_index)
Expand Down
4 changes: 3 additions & 1 deletion port.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ struct foreign_clock *port_compute_best(struct port *port);
* @param port A pointer previously obtained via port_open().
* @param event One of the @a fsm_event codes.
* @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
Expand Down

0 comments on commit 0dbdd9c

Please sign in to comment.