Message ID | 20230314205429.1174295-1-peterx@redhat.com |
---|---|
State | New |
Headers | show |
Series | migration: Wait on preempt channel in preempt thread | expand |
Peter Xu <peterx@redhat.com> wrote: > QEMU main thread will wait until dest preempt channel established during > processing the LISTEN command (within the whole postcopy PACKAGED data), by > waiting on the semaphore postcopy_qemufile_dst_done. > > That's racy, because it's possible that the dest QEMU main thread hasn't > yet accept()ed the new connection when processing the LISTEN event. The > sem_wait() will yield the main thread without being able to run anything > else including the accept() of the new socket, which can cause deadlock > within the main thread. > > To avoid the race, move the "wait channel" from main thread to the preempt > thread right at the start. > > Reported-by: Peter Maydell <peter.maydell@linaro.org> > Fixes: 5655aab079 ("migration: Postpone postcopy preempt channel to be after main") > Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> > Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> queued.
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index f54f44d899..41c0713650 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -1197,11 +1197,6 @@ int postcopy_ram_incoming_setup(MigrationIncomingState *mis) } if (migrate_postcopy_preempt()) { - /* - * The preempt channel is established in asynchronous way. Wait - * for its completion. - */ - qemu_sem_wait(&mis->postcopy_qemufile_dst_done); /* * This thread needs to be created after the temp pages because * it'll fetch RAM_CHANNEL_POSTCOPY PostcopyTmpPage immediately. @@ -1668,6 +1663,12 @@ void *postcopy_preempt_thread(void *opaque) qemu_sem_post(&mis->thread_sync_sem); + /* + * The preempt channel is established in asynchronous way. Wait + * for its completion. + */ + qemu_sem_wait(&mis->postcopy_qemufile_dst_done); + /* Sending RAM_SAVE_FLAG_EOS to terminate this thread */ qemu_mutex_lock(&mis->postcopy_prio_thread_mutex); while (1) {