Skip to content
This repository has been archived by the owner on Aug 22, 2021. It is now read-only.

Commit

Permalink
Fix assertion failures on FreeBSD due to kevent() returning multiple …
Browse files Browse the repository at this point in the history
…entries for the same file event source.

Maintain linked lists of all returned events for each event source, instead of supporting just a single event per event source.
  • Loading branch information
ambrop72 committed Jan 10, 2016
1 parent 4b76199 commit fac69ce
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 26 deletions.
61 changes: 37 additions & 24 deletions system/BReactor_badvpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,21 @@ static void set_kevent_fd_pointers (BReactor *bsys)
for (int i = 0; i < bsys->kevent_results_num; i++) {
struct kevent *event = &bsys->kevent_results[i];
ASSERT(event->udata)

int *tag = event->udata;
switch (*tag) {
case KEVENT_TAG_FD: {
BFileDescriptor *bfd = UPPER_OBJECT(tag, BFileDescriptor, kevent_tag);
ASSERT(bfd->active)
ASSERT(!bfd->kevent_returned_ptr)
bfd->kevent_returned_ptr = (int **)&event->udata;
bsys->kevent_prev_event[i] = bfd->kevent_last_event;
bfd->kevent_last_event = i;
} break;

case KEVENT_TAG_KEVENT: {
BReactorKEvent *kev = UPPER_OBJECT(tag, BReactorKEvent, kevent_tag);
ASSERT(kev->reactor == bsys)
ASSERT(!kev->kevent_returned_ptr)
kev->kevent_returned_ptr = (int **)&event->udata;
bsys->kevent_prev_event[i] = kev->kevent_last_event;
kev->kevent_last_event = i;
} break;

default:
Expand Down Expand Up @@ -873,7 +874,8 @@ int BReactor_Exec (BReactor *bsys)
// dispatch kevent
if (bsys->kevent_results_pos < bsys->kevent_results_num) {
// grab event
struct kevent *event = &bsys->kevent_results[bsys->kevent_results_pos];
int event_index = bsys->kevent_results_pos;
struct kevent *event = &bsys->kevent_results[event_index];
bsys->kevent_results_pos++;

// check if the event was removed
Expand All @@ -888,10 +890,11 @@ int BReactor_Exec (BReactor *bsys)
// get BFileDescriptor
BFileDescriptor *bfd = UPPER_OBJECT(tag, BFileDescriptor, kevent_tag);
ASSERT(bfd->active)
ASSERT(bfd->kevent_returned_ptr == (int **)&event->udata)

// zero pointer to the kevent entry
bfd->kevent_returned_ptr = NULL;
// when we get to the last event for this fd, reset kevent_last_event
if (event_index == bfd->kevent_last_event) {
bfd->kevent_last_event = -1;
}

// calculate event to report
int events = 0;
Expand All @@ -917,10 +920,11 @@ int BReactor_Exec (BReactor *bsys)
// get BReactorKEvent
BReactorKEvent *kev = UPPER_OBJECT(tag, BReactorKEvent, kevent_tag);
ASSERT(kev->reactor == bsys)
ASSERT(kev->kevent_returned_ptr == (int **)&event->udata)

// zero pointer to the kevent entry
kev->kevent_returned_ptr = NULL;
// when we get to the last event for this fd, reset kevent_last_event
if (event_index == kev->kevent_last_event) {
kev->kevent_last_event = -1;
}

// call handler
BLog(BLOG_DEBUG, "Dispatching kevent");
Expand Down Expand Up @@ -1109,8 +1113,8 @@ int BReactor_AddFileDescriptor (BReactor *bsys, BFileDescriptor *bs)
// set kevent tag
bs->kevent_tag = KEVENT_TAG_FD;

// set kevent returned pointer
bs->kevent_returned_ptr = NULL;
// have no events
bs->kevent_last_event = -1;

#endif

Expand Down Expand Up @@ -1163,9 +1167,13 @@ void BReactor_RemoveFileDescriptor (BReactor *bsys, BFileDescriptor *bs)
// delete kevents
update_kevent_fd_events(bsys, bs, 0);

// write through kevent returned pointer
if (bs->kevent_returned_ptr) {
*bs->kevent_returned_ptr = NULL;
// invalidate any events
int event_index = bs->kevent_last_event;
while (event_index != -1) {
ASSERT(event_index >= 0 && event_index < bsys->kevent_results_num)
struct kevent *event = &bsys->kevent_results[event_index];
event->udata = NULL;
event_index = bsys->kevent_prev_event[event_index];
}

#endif
Expand Down Expand Up @@ -1316,8 +1324,8 @@ int BReactorKEvent_Init (BReactorKEvent *o, BReactor *reactor, BReactorKEvent_ha
// set kevent tag
o->kevent_tag = KEVENT_TAG_KEVENT;

// set kevent returned pointer
o->kevent_returned_ptr = NULL;
// have no events
o->kevent_last_event = -1;

DebugObject_Init(&o->d_obj);
DebugCounter_Increment(&o->reactor->d_kevent_ctr);
Expand All @@ -1326,12 +1334,17 @@ int BReactorKEvent_Init (BReactorKEvent *o, BReactor *reactor, BReactorKEvent_ha

void BReactorKEvent_Free (BReactorKEvent *o)
{
BReactor *reactor = o->reactor;
DebugObject_Free(&o->d_obj);
DebugCounter_Decrement(&o->reactor->d_kevent_ctr);

// write through kevent returned pointer
if (o->kevent_returned_ptr) {
*o->kevent_returned_ptr = NULL;
DebugCounter_Decrement(&reactor->d_kevent_ctr);

// invalidate any events
int event_index = o->kevent_last_event;
while (event_index != -1) {
ASSERT(event_index >= 0 && event_index < reactor->kevent_results_num)
struct kevent *event = &reactor->kevent_results[event_index];
event->udata = NULL;
event_index = reactor->kevent_prev_event[event_index];
}

// delete kevent
Expand All @@ -1340,7 +1353,7 @@ void BReactorKEvent_Free (BReactorKEvent *o)
event.ident = o->ident;
event.filter = o->filter;
event.flags = EV_DELETE;
ASSERT_FORCE(kevent(o->reactor->kqueue_fd, &event, 1, NULL, 0, NULL) == 0)
ASSERT_FORCE(kevent(reactor->kqueue_fd, &event, 1, NULL, 0, NULL) == 0)
}

#endif
Expand Down
5 changes: 3 additions & 2 deletions system/BReactor_badvpn.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ typedef struct BFileDescriptor_t {

#ifdef BADVPN_USE_KEVENT
int kevent_tag;
int **kevent_returned_ptr;
int kevent_last_event;
#endif

#ifdef BADVPN_USE_POLL
Expand Down Expand Up @@ -265,6 +265,7 @@ typedef struct {
#ifdef BADVPN_USE_KEVENT
int kqueue_fd;
struct kevent kevent_results[BSYSTEM_MAX_RESULTS];
int kevent_prev_event[BSYSTEM_MAX_RESULTS];
int kevent_results_num;
int kevent_results_pos;
#endif
Expand Down Expand Up @@ -531,7 +532,7 @@ typedef struct {
uintptr_t ident;
short filter;
int kevent_tag;
int **kevent_returned_ptr;
int kevent_last_event;
DebugObject d_obj;
} BReactorKEvent;

Expand Down

1 comment on commit fac69ce

@ambrop72
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes lead to crashing on (ARM) android

Hey, I don't think that's possible because the kevent code is not used on Android (Android is Linux so it should use the epoll code).

Please sign in to comment.