Fix epoll-oneshot may cause crash (#3158)

This commit is contained in:
jimying 2022-07-06 09:19:31 +08:00 committed by GitHub
parent cbc2051d7b
commit b9db6ac058
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 26 additions and 23 deletions

View File

@ -831,6 +831,14 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
}
continue;
}
if (ioqueue->use_epolloneshot) {
/* We are not processing this event, but we still need to rearm
* to receive future events.
*/
if (!IS_CLOSING(h))
ioqueue_add_to_set(ioqueue, h, 0);
}
}
for (i=0; i<event_cnt; ++i) {
if (queue[i].key->grp_lock)
@ -874,6 +882,24 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
}
}
if (ioqueue->use_epolloneshot) {
/* When using EPOLLONESHOT, we will receive one-shot notification
* for the associated file descriptor, after which the file
* descriptor is disabled in the interest list and no other events
* will be reported. Note the following cases can happen:
* - we do not want to process a reported event (i.e. event_cnt <
* count)
* - we process the event, but the processing doesn't rearm the file
* descriptor (such as during processing failure)
* So we need to make sure to rearm the file descriptor here with
* a new event mask.
*/
pj_ioqueue_lock_key(queue[i].key);
if (!IS_CLOSING(queue[i].key))
ioqueue_add_to_set(ioqueue, queue[i].key, 0);
pj_ioqueue_unlock_key(queue[i].key);
}
#if PJ_IOQUEUE_HAS_SAFE_UNREG
decrement_counter(queue[i].key);
#endif
@ -883,29 +909,6 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
"ioqueue", 0);
}
if (ioqueue->use_epolloneshot) {
/* When using EPOLLONESHOT, we will receive one-shot notification for
* the associated file descriptor, after which the file descriptor
* is disabled in the interest list and no other events will be
* reported.
* Note the following cases can happen:
* - we do not want to process a reported event (i.e. event_cnt < count)
* - we process the event, but the processing doesn't rearm the file
* descriptor (such as during processing failure)
* So we need to make sure to rearm the file descriptor here with
* a new event mask.
*/
for (i = 0; i < count; ++i) {
pj_ioqueue_key_t *h =
(pj_ioqueue_key_t *)(epoll_data_type)events[i].epoll_data;
pj_ioqueue_lock_key(h);
if (!IS_CLOSING(h))
ioqueue_add_to_set(ioqueue, h, 0);
pj_ioqueue_unlock_key(h);
}
}
/* Special case:
* When epoll returns > 0 but event_cnt, the number of events
* we want to process, is zero.