summaryrefslogtreecommitdiff
path: root/src/lib/ecore
diff options
context:
space:
mode:
authorIvan Furs <i.furs@samsung.com>2017-04-19 10:29:27 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-04-19 10:33:03 +0900
commitc9469e0b011c1e4ee2f5e86e5df2a334820b6c6a (patch)
treef33142182e5b37d72d7b83d6789d18d4e5a95270 /src/lib/ecore
parent91e87c5f0501e37f9513b8391bffc91ac7da93d0 (diff)
ecore_pipe: Fixed dead lock with epoll
See a76ebea2d840ecc575efb025574c15503225b83f and the following commits on this file. The following test scenario let to easily reproducible application hangs: elementary_test -to "Icon Desktops" # then scroll vigorously with the mouse wheel up/down This patch was applied as a new revision on the below diff: Differential Revision: https://phab.enlightenment.org/D4754
Diffstat (limited to 'src/lib/ecore')
-rw-r--r--src/lib/ecore/ecore_pipe.c155
1 files changed, 73 insertions, 82 deletions
diff --git a/src/lib/ecore/ecore_pipe.c b/src/lib/ecore/ecore_pipe.c
index 1dfb8640e4..2949f22392 100644
--- a/src/lib/ecore/ecore_pipe.c
+++ b/src/lib/ecore/ecore_pipe.c
@@ -370,11 +370,11 @@ ecore_pipe_full_add(Ecore_Pipe_Cb handler,
370 p->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 370 p->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
371 eina_file_close_on_exec(p->pollfd, EINA_TRUE); 371 eina_file_close_on_exec(p->pollfd, EINA_TRUE);
372 372
373 pollev.data.ptr = (void *)(uintptr_t)(p->fd_read); 373 pollev.data.ptr = &(p->fd_read);
374 pollev.events = EPOLLIN; 374 pollev.events = EPOLLIN;
375 epoll_ctl(p->pollfd, EPOLL_CTL_ADD, p->fd_read, &pollev); 375 epoll_ctl(p->pollfd, EPOLL_CTL_ADD, p->fd_read, &pollev);
376 376
377 pollev.data.ptr = (void *)(uintptr_t)(p->timerfd); 377 pollev.data.ptr = &(p->timerfd);
378 pollev.events = EPOLLIN; 378 pollev.events = EPOLLIN;
379 epoll_ctl(p->pollfd, EPOLL_CTL_ADD, p->timerfd, &pollev); 379 epoll_ctl(p->pollfd, EPOLL_CTL_ADD, p->timerfd, &pollev);
380#endif 380#endif
@@ -535,104 +535,95 @@ _ecore_pipe_wait(Ecore_Pipe *p,
535{ 535{
536 int64_t timerfdbuf; 536 int64_t timerfdbuf;
537 struct epoll_event pollincoming[2]; 537 struct epoll_event pollincoming[2];
538 double end = 0.0;
539 double timeout; 538 double timeout;
540 int ret; 539 int ret;
541 int total = 0; 540 int total = 0;
542 int time_exit=-1; 541 int time_exit=-1;
542 Eina_Bool fd_read_found;
543 Eina_Bool fd_timer_found;
543 struct itimerspec tspec_new; 544 struct itimerspec tspec_new;
544 struct itimerspec tspec_old;
545 545
546 EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1); 546 EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
547 if (p->fd_read == PIPE_FD_INVALID) 547 if (p->fd_read == PIPE_FD_INVALID)
548 return -1; 548 return -1;
549 549
550 if (wait >= 0.0)
551 end = ecore_time_get() + wait;
552 timeout = wait; 550 timeout = wait;
553 551 int sec, usec;
554 while (message_count > 0 && (timeout > 0.0 || wait <= 0.0)) 552 if ( wait >= 0.0)
555 { 553 {
556 time_exit = -1; 554 if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
557 if (wait >= 0.0)
558 { 555 {
559 /* finite() tests for NaN, too big, too small, and infinity. */ 556 tspec_new.it_value.tv_sec = 0;
560 if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0))) 557 tspec_new.it_value.tv_nsec = 0;
561 { 558 tspec_new.it_interval.tv_sec = 0;
562 tspec_new.it_value.tv_sec = 0; 559 tspec_new.it_interval.tv_nsec = 0;
563 tspec_new.it_value.tv_nsec = 0; 560 time_exit = 0;
564 tspec_new.it_interval.tv_sec = 0;
565 tspec_new.it_interval.tv_nsec = 0;
566 time_exit = 0;
567 }
568 else if (timeout > 0.0)
569 {
570 int sec, usec;
571#ifdef FIX_HZ
572 timeout += (0.5 / HZ);
573#endif
574 sec = (int)timeout;
575 usec = (int)((timeout - (double)sec) * 1000000000);
576 tspec_new.it_value.tv_sec = sec;
577 tspec_new.it_value.tv_nsec = (int)(usec) % 1000000000;
578 tspec_new.it_interval.tv_sec = 0;
579 tspec_new.it_interval.tv_nsec = 0;
580
581 }
582 timerfd_settime(p->timerfd, 0, &tspec_new, &tspec_old);
583 } 561 }
584 562 else
585 ret = epoll_wait(p->pollfd, pollincoming, 2, time_exit);
586
587 if (ret > 0)
588 { 563 {
589 Eina_Bool fd_read_found = EINA_FALSE; 564#ifdef FIX_HZ
590 Eina_Bool fd_timer_found = EINA_FALSE; 565 timeout += (0.5 / HZ);
591 566#endif
592 for (int i = 0; i < ret;i++) 567 sec = (int)timeout;
593 { 568 usec = (int)((timeout - (double)sec) * 1000000000);
594 if ((&p->fd_read == pollincoming[i].data.ptr)) 569 tspec_new.it_value.tv_sec = sec;
595 fd_read_found = EINA_TRUE; 570 tspec_new.it_value.tv_nsec = (int)(usec) % 1000000000;
596 if ((&p->timerfd == pollincoming[i].data.ptr)) 571 tspec_new.it_interval.tv_sec = 0;
597 fd_timer_found = EINA_TRUE; 572 tspec_new.it_interval.tv_nsec = 0;
598 } 573 timerfd_settime(p->timerfd, 0, &tspec_new, NULL);
599 574 }
600 p->handling++; 575 }
601 if (fd_read_found)
602 {
603 _ecore_pipe_read(p, NULL);
604 message_count -= p->message;
605 total += p->message;
606 p->message = 0;
607 }
608 576
609 if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID)) 577 while ((ret = epoll_wait(p->pollfd, pollincoming, 2, time_exit)) > 0)
610 { 578 {
611 if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf)) 579 fd_read_found = EINA_FALSE;
612 < sizeof(timerfdbuf)) 580 fd_timer_found = EINA_FALSE;
613 WRN("Could not read timerfd data"); 581
614 _ecore_pipe_unhandle(p); 582 for (int i = 0; i < ret;i++)
615 break; 583 {
616 } 584 if ((&p->fd_read == pollincoming[i].data.ptr))
617 _ecore_pipe_unhandle(p); 585 fd_read_found = EINA_TRUE;
618 } 586 if ((&p->timerfd == pollincoming[i].data.ptr))
619 else if (ret == 0) 587 fd_timer_found = EINA_TRUE;
620 { 588 }
621 break; 589
622 } 590 p->handling++;
591 if (fd_read_found)
592 {
593 _ecore_pipe_read(p, NULL);
594 message_count -= p->message;
595 total += p->message;
596 p->message = 0;
597 if (message_count <= 0)
598 {
599 _ecore_pipe_unhandle(p);
600 break;
601 }
602 }
603
604 if ((fd_timer_found) && (p->timerfd != PIPE_FD_INVALID))
605 {
606 if (pipe_read(p->timerfd, &timerfdbuf, sizeof(timerfdbuf))
607 < sizeof(int64_t))
608 WRN("Could not read timerfd data");
609 _ecore_pipe_unhandle(p);
610 break;
611 }
612 _ecore_pipe_unhandle(p);
613 }
614 if (ret < 0)
615 {
616 if (errno != EBADF)
617 WRN("epoll file descriptor is not a valid");
618 else if (errno != EINVAL)
619 WRN("epoll file descriptor is not an epoll file descriptor, or maxevents is less than or equal to zero.");
620 else if (errno != EFAULT)
621 WRN("The memory area pointed to by epoll_event is not accessible with write permissions.");
623 else if (errno != EINTR) 622 else if (errno != EINTR)
624 { 623 WRN("The call was interrupted by a signal handler before any of the requested epoll_event "
625 if (p->fd_read != PIPE_FD_INVALID) 624 "occurred or the timeout expired; see signal(7).");
626 {
627 close(p->fd_read);
628 p->fd_read = PIPE_FD_INVALID;
629 }
630 break;
631 }
632
633 if (wait >= 0.0)
634 timeout = end - ecore_time_get();
635 } 625 }
626
636 return total; 627 return total;
637} 628}
638 629