Skip to content

Commit eec3a34

Browse files
fyin1wenlingz
authored andcommitted
dm: fix the race issue in mevent_del
Peter, Thomas and Shuo raised one race issue in mevent_del. It happens like following: Thread mevent_dispatch Thread mevent_delete_event epoll_ctl_del free(evp) mevent_handle with freed evp The fixing is adding sync between mevent_delete_event and mevent_handle in mevent_dispatch. Thread mevent_dispatch Thread mevent_delete_event add evp to del_list notify mevent_dispatch return mevent_handle Remove evp from del_list Remove evp from epoll_fd closefd() free(evp) Tracked-On: #1877 Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent 87e7bdb commit eec3a34

File tree

1 file changed

+76
-27
lines changed

1 file changed

+76
-27
lines changed

devicemodel/core/mevent.c

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,20 @@ static int mevent_pipefd[2];
5656
static pthread_mutex_t mevent_lmutex = PTHREAD_MUTEX_INITIALIZER;
5757

5858
struct mevent {
59-
void (*me_func)(int, enum ev_type, void *);
60-
int me_fd;
61-
enum ev_type me_type;
62-
void *me_param;
63-
int me_cq;
64-
int me_state;
65-
int me_closefd;
66-
67-
LIST_ENTRY(mevent) me_list;
59+
void (*me_func)(int, enum ev_type, void *);
60+
int me_fd;
61+
enum ev_type me_type;
62+
void *me_param;
63+
int me_cq;
64+
int me_state;
65+
66+
int closefd;
67+
LIST_ENTRY(mevent) me_list;
6868
};
6969

7070
static LIST_HEAD(listhead, mevent) global_head;
71+
/* List holds the mevent node which is requested to deleted */
72+
static LIST_HEAD(del_listhead, mevent) del_head;
7173

7274
static void
7375
mevent_qlock(void)
@@ -81,6 +83,12 @@ mevent_qunlock(void)
8183
pthread_mutex_unlock(&mevent_lmutex);
8284
}
8385

86+
static bool
87+
is_dispatch_thread(void)
88+
{
89+
return (pthread_self() == mevent_tid);
90+
}
91+
8492
static void
8593
mevent_pipe_read(int fd, enum ev_type type, void *param)
8694
{
@@ -138,15 +146,11 @@ static void
138146
mevent_destroy(void)
139147
{
140148
struct mevent *mevp, *tmpp;
141-
struct epoll_event ee;
142149

143150
mevent_qlock();
144-
145151
list_foreach_safe(mevp, &global_head, me_list, tmpp) {
146152
LIST_REMOVE(mevp, me_list);
147-
ee.events = mevent_kq_filter(mevp);
148-
ee.data.ptr = mevp;
149-
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, mevp->me_fd, &ee);
153+
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, mevp->me_fd, NULL);
150154

151155
if ((mevp->me_type == EVF_READ ||
152156
mevp->me_type == EVF_READ_ET ||
@@ -158,6 +162,21 @@ mevent_destroy(void)
158162
free(mevp);
159163
}
160164

165+
/* the mevp in del_head was removed from epoll when add it
166+
* to del_head already.
167+
*/
168+
list_foreach_safe(mevp, &del_head, me_list, tmpp) {
169+
LIST_REMOVE(mevp, me_list);
170+
171+
if ((mevp->me_type == EVF_READ ||
172+
mevp->me_type == EVF_READ_ET ||
173+
mevp->me_type == EVF_WRITE ||
174+
mevp->me_type == EVF_WRITE_ET) &&
175+
mevp->me_fd != STDIN_FILENO)
176+
close(mevp->me_fd);
177+
178+
free(mevp);
179+
}
161180
mevent_qunlock();
162181
}
163182

@@ -169,9 +188,9 @@ mevent_handle(struct epoll_event *kev, int numev)
169188

170189
for (i = 0; i < numev; i++) {
171190
mevp = kev[i].data.ptr;
172-
/* XXX check for EV_ERROR ? */
173191

174-
(*mevp->me_func)(mevp->me_fd, mevp->me_type, mevp->me_param);
192+
if (mevp->me_state)
193+
(*mevp->me_func)(mevp->me_fd, mevp->me_type, mevp->me_param);
175194
}
176195
}
177196

@@ -210,6 +229,7 @@ mevent_add(int tfd, enum ev_type type,
210229
mevp->me_type = type;
211230
mevp->me_func = func;
212231
mevp->me_param = param;
232+
mevp->me_state = 1;
213233

214234
ee.events = mevent_kq_filter(mevp);
215235
ee.data.ptr = mevp;
@@ -267,23 +287,50 @@ mevent_disable(struct mevent *evp)
267287
return ret;
268288
}
269289

290+
static void
291+
mevent_add_to_del_list(struct mevent *evp, int closefd)
292+
{
293+
mevent_qlock();
294+
LIST_INSERT_HEAD(&del_head, evp, me_list);
295+
mevent_qunlock();
296+
297+
mevent_notify();
298+
}
299+
300+
static void
301+
mevent_drain_del_list(void)
302+
{
303+
struct mevent *evp, *tmpp;
304+
305+
mevent_qlock();
306+
list_foreach_safe(evp, &del_head, me_list, tmpp) {
307+
LIST_REMOVE(evp, me_list);
308+
if (evp->closefd) {
309+
close(evp->me_fd);
310+
}
311+
free(evp);
312+
}
313+
mevent_qunlock();
314+
}
315+
270316
static int
271317
mevent_delete_event(struct mevent *evp, int closefd)
272318
{
273-
struct epoll_event ee;
274-
275319
mevent_qlock();
276320
LIST_REMOVE(evp, me_list);
277321
mevent_qunlock();
322+
evp->me_state = 0;
323+
evp->closefd = closefd;
278324

279-
ee.events = mevent_kq_filter(evp);
280-
ee.data.ptr = evp;
281-
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evp->me_fd, &ee);
282-
283-
if (closefd)
284-
close(evp->me_fd);
285-
286-
free(evp);
325+
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evp->me_fd, NULL);
326+
if (!is_dispatch_thread()) {
327+
mevent_add_to_del_list(evp, closefd);
328+
} else {
329+
if (evp->closefd) {
330+
close(evp->me_fd);
331+
}
332+
free(evp);
333+
}
287334
return 0;
288335
}
289336

@@ -322,6 +369,8 @@ mevent_deinit(void)
322369
{
323370
mevent_destroy();
324371
close(epoll_fd);
372+
if (mevent_pipefd[1] != 0)
373+
close(mevent_pipefd[1]);
325374
}
326375

327376
void
@@ -366,9 +415,9 @@ mevent_dispatch(void)
366415
* Handle reported events
367416
*/
368417
mevent_handle(eventlist, ret);
418+
mevent_drain_del_list();
369419

370420
suspend_mode = vm_get_suspend_mode();
371-
372421
if ((suspend_mode != VM_SUSPEND_NONE) &&
373422
(suspend_mode != VM_SUSPEND_SYSTEM_RESET) &&
374423
(suspend_mode != VM_SUSPEND_SUSPEND))

0 commit comments

Comments
 (0)