dm: fix mevent mutex deadlock issue

'mevent_lmutex' is initialized as default type,
 while attempting to recursively lock on this
 kind of mutext results in undefined behaviour.

 Recursively lock on 'mevent_lmutex' can be detected
 in mevent thread when user tries to trigger system
 reset from user VM, in this case, user VM reboot hang.

 The backtrace for this issue:
  #1 in mevent_qlock () at core/mevent.c:93
  #2 in mevent_delete_even at core/mevent.c:357
    ===>Recursively LOCK
  #3 in mevent_delete_close at core/mevent.c:387
  #4 in acrn_timer_deinit at core/timer.c:106
  #5 in virtio_reset_dev at hw/pci/virtio/virtio.c:171
  #6 in virtio_console_reset at
     hw/pci/virtio/virtio_console.c:196
  #7 in virtio_console_destroy at
    hw/pci/virtio/virtio_console.c:1015
  #8 in virtio_console_teardown_backend at
    hw/pci/virtio/virtio_console.c:1042
  #9 in mevent_drain_del_list () at
    core/mevent.c:348 ===> 1st LOCK
  #10 in mevent_dispatch () at core/mevent.c:472
  #11 in main at core/main.c:1110

  So the root cause is:
  mevent_mutex lock is recursively locked by mevent thread
  itself (#9 for this first lock and #2 for recursively lock),
  which is not allowed for mutex with default attribute.

  This patch changes the mutex type of 'mevent_lmutex'
  from default to "PTHREAD_MUTEX_RECURSIVE", because
  recrusively lock shall be allowed as user of mevent
  may call mevent functions (where mutex lock maybe required)
  in teardown callbacks.

Tracked-On: #7133
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Yonghua Huang 2022-02-15 10:23:39 +03:00 committed by acrnsi-robot
parent e2f1990548
commit b4386566ef

View File

@ -54,7 +54,7 @@
static int epoll_fd;
static pthread_t mevent_tid;
static int mevent_pipefd[2];
static pthread_mutex_t mevent_lmutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mevent_lmutex;
struct mevent {
void (*run)(int, enum ev_type, void *);
@ -376,6 +376,13 @@ mevent_set_name(void)
int
mevent_init(void)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mevent_lmutex, &attr);
pthread_mutexattr_destroy(&attr);
epoll_fd = epoll_create1(0);
if (epoll_fd >= 0)
@ -391,6 +398,8 @@ mevent_deinit(void)
close(epoll_fd);
if (mevent_pipefd[1] != 0)
close(mevent_pipefd[1]);
pthread_mutex_destroy(&mevent_lmutex);
}
void