VirtualBox

Changeset 85346 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 15, 2020 9:00:35 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
139332
Message:

Devices/Audio/DrvHostPulseAudio: Don't wait indefinitely for the connection to the pulseaudio server to be established as it might hang under certain circumstances causing the VM to hang during startup

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r82968 r85346  
    2929#include <iprt/mem.h>
    3030#include <iprt/uuid.h>
     31#include <iprt/semaphore.h>
    3132
    3233RT_C_DECLS_BEGIN
     
    321322
    322323/**
     324 * Context status changed, init variant signalling our own event semaphore
     325 * so we can do a timed wait.
     326 */
     327static void paContextCbStateChangedInit(pa_context *pCtx, void *pvUser)
     328{
     329    AssertPtrReturnVoid(pCtx);
     330
     331    RTSEMEVENT hEvtInit = (RTSEMEVENT)pvUser;
     332    AssertReturnVoid(hEvtInit != NIL_RTSEMEVENT);
     333
     334    switch (pa_context_get_state(pCtx))
     335    {
     336        case PA_CONTEXT_READY:
     337        case PA_CONTEXT_TERMINATED:
     338        case PA_CONTEXT_FAILED:
     339            RTSemEventSignal(hEvtInit);
     340            break;
     341
     342        default:
     343            break;
     344    }
     345}
     346
     347
     348/**
    323349 * Context status changed.
    324350 */
     
    660686            LogRel(("PulseAudio: Failed to start threaded mainloop: %s\n",
    661687                     pa_strerror(pa_context_errno(pThis->pContext))));
    662             break;
    663         }
    664 
    665         /* Install a global callback to known if something happens to our acquired context. */
    666         pa_context_set_state_callback(pThis->pContext, paContextCbStateChanged, pThis /* pvUserData */);
     688            rc = VERR_AUDIO_BACKEND_INIT_FAILED;
     689            break;
     690        }
     691
     692        RTSEMEVENT hEvtInit = NIL_RTSEMEVENT;
     693        rc = RTSemEventCreate(&hEvtInit);
     694        if (RT_FAILURE(rc))
     695        {
     696            LogRel(("PulseAudio: Failed to create init event semaphore: %Rrc\n", rc));
     697            break;
     698        }
     699
     700        /*
     701         * Install a dedicated init state callback so we can do a timed wait on our own event semaphore if connecting
     702         * to the pulseaudio server takes too long.
     703         */
     704        pa_context_set_state_callback(pThis->pContext, paContextCbStateChangedInit, hEvtInit /* pvUserData */);
    667705
    668706        pa_threaded_mainloop_lock(pThis->pMainLoop);
    669707        fLocked = true;
    670708
    671         if (pa_context_connect(pThis->pContext, NULL /* pszServer */,
    672                                PA_CONTEXT_NOFLAGS, NULL) < 0)
    673         {
     709        if (!pa_context_connect(pThis->pContext, NULL /* pszServer */,
     710                                PA_CONTEXT_NOFLAGS, NULL))
     711        {
     712            /* Wait on our init event semaphore and time out if connecting to the pulseaudio server takes too long. */
     713            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     714            fLocked = false;
     715
     716            rc = RTSemEventWait(hEvtInit, RT_MS_10SEC); /* 10 seconds should be plenty. */
     717
     718            pa_threaded_mainloop_lock(pThis->pMainLoop);
     719            fLocked = true;
     720
     721            pa_context_state_t cstate = pa_context_get_state(pThis->pContext);
     722            if (cstate != PA_CONTEXT_READY)
     723            {
     724                LogRel(("PulseAudio: Failed to initialize context (state %d, rc=%Rrc)\n", cstate, rc));
     725                if (RT_SUCCESS(rc))
     726                    rc = VERR_AUDIO_BACKEND_INIT_FAILED;
     727            }
     728        }
     729        else
    674730            LogRel(("PulseAudio: Failed to connect to server: %s\n",
    675731                     pa_strerror(pa_context_errno(pThis->pContext))));
    676             break;
    677         }
    678 
    679         /* Wait until the pThis->pContext is ready. */
    680         for (;;)
    681         {
    682             if (!pThis->fAbortLoop)
    683                 pa_threaded_mainloop_wait(pThis->pMainLoop);
    684             pThis->fAbortLoop = false;
    685 
    686             pa_context_state_t cstate = pa_context_get_state(pThis->pContext);
    687             if (cstate == PA_CONTEXT_READY)
    688                 break;
    689             else if (   cstate == PA_CONTEXT_TERMINATED
    690                      || cstate == PA_CONTEXT_FAILED)
    691             {
    692                 LogRel(("PulseAudio: Failed to initialize context (state %d)\n", cstate));
    693                 break;
    694             }
    695         }
     732
     733        RTSemEventDestroy(hEvtInit);
     734
     735        /* Install the main state changed callback to know if something happens to our acquired context. */
     736        pa_context_set_state_callback(pThis->pContext, paContextCbStateChanged, pThis /* pvUserData */);
    696737    }
    697738    while (0);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette