VirtualBox

Changeset 86495 in vbox


Ignore:
Timestamp:
Oct 8, 2020 1:04:26 PM (4 years ago)
Author:
vboxsync
Message:

VBoxSVC/HostPowerServiceLinux: Use RTThreadPoke on the notification thread if it doesn't seem to respond to dbus_connection_close() after 10 ms. Also, grab an extra reference on the connection so both the thread and the destruction have one to drop, otherwise we'd be in trouble if the other side terminates the connection and the thread exits early. bugref:9841

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/dbus-calls.h

    r82968 r86495  
    4545 RT_PROXY_STUB(dbus_free_string_array, void, (char **str_array), \
    4646                 (str_array)) \
     47 RT_PROXY_STUB(dbus_connection_ref, DBusConnection *, (DBusConnection *connection), \
     48                 (connection)) \
    4749 RT_PROXY_STUB(dbus_connection_unref, void, (DBusConnection *connection), \
    4850                 (connection)) \
  • trunk/src/VBox/Main/src-server/linux/HostPowerLinux.cpp

    r82968 r86495  
    4545HostPowerServiceLinux::HostPowerServiceLinux(VirtualBox *aVirtualBox)
    4646  : HostPowerService(aVirtualBox)
    47   , mThread(NULL)
     47  , mThread(NIL_RTTHREAD)
    4848  , mpConnection(NULL)
    4949{
     
    7676    if (checkDBusError(&error, &mpConnection))
    7777        return;
     78
     79    /* Grab another reference so that both the destruct and thread each has one: */
     80    DBusConnection *pForAssert = dbus_connection_ref(mpConnection);
     81    Assert(pForAssert == mpConnection); RT_NOREF(pForAssert);
     82
    7883    /* Create the new worker thread. */
    7984    rc = RTThreadCreate(&mThread, HostPowerServiceLinux::powerChangeNotificationThread, this, 0 /* cbStack */,
    8085                        RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, "MainPower");
    8186    if (RT_FAILURE(rc))
     87    {
    8288        LogRel(("HostPowerServiceLinux: RTThreadCreate failed with %Rrc\n", rc));
     89        dbus_connection_unref(mpConnection);
     90    }
    8391}
    8492
     
    8694HostPowerServiceLinux::~HostPowerServiceLinux()
    8795{
    88     int rc;
    89     RTMSINTERVAL cMillies = 5000;
    90 
    9196    /* Closing the connection should cause the event loop to exit. */
    9297    LogFunc((": Stopping thread\n"));
    9398    if (mpConnection)
     99    {
    94100        dbus_connection_close(mpConnection);
     101        dbus_connection_unref(mpConnection);
     102        mpConnection = NULL;
     103    }
    95104
    96     rc = RTThreadWait(mThread, cMillies, NULL);
    97     if (rc != VINF_SUCCESS)
    98         LogRelThisFunc(("RTThreadWait() for %u ms failed with %Rrc\n", cMillies, rc));
    99     mThread = NIL_RTTHREAD;
     105    if (mThread != NIL_RTTHREAD)
     106    {
     107        /* HACK ALERT! This poke call should _not_ be necessary as dbus_connection_close()
     108                       should close the socket and force the poll/dbus_connection_read_write
     109                       call to return with POLLHUP/FALSE.  It does so when stepping it in the
     110                       debugger, but not in real life (asan build; dbus-1.12.20-1.fc32; linux 5.8).
     111
     112                       Poking the thread is a crude crude way to wake it up from whatever
     113                       stuff it's actually blocked on and realize that the connection has
     114                       been dropped. */
     115
     116        uint64_t msElapsed = RTTimeMilliTS();
     117        int vrc = RTThreadWait(mThread, 10 /*ms*/, NULL);
     118        if (RT_FAILURE(vrc))
     119        {
     120            RTThreadPoke(mThread);
     121            vrc = RTThreadWait(mThread, RT_MS_5SEC, NULL);
     122        }
     123        msElapsed = RTTimeMilliTS() - msElapsed;
     124        if (vrc != VINF_SUCCESS)
     125            LogRelThisFunc(("RTThreadWait() failed after %llu ms: %Rrc\n", msElapsed, vrc));
     126        mThread = NIL_RTTHREAD;
     127    }
    100128}
    101129
     
    114142        for (;;)
    115143        {
    116             DBusMessageIter args;
    117             dbus_bool_t fSuspend;
    118 
    119144            pMessage = dbus_connection_pop_message(pConnection);
    120145            if (pMessage == NULL)
    121146                break;
     147
    122148            /* The systemd-logind interface notification. */
     149            DBusMessageIter args;
    123150            if (   dbus_message_is_signal(pMessage, "org.freedesktop.login1.Manager", "PrepareForSleep")
    124151                && dbus_message_iter_init(pMessage, &args)
    125152                && dbus_message_iter_get_arg_type(&args) == DBUS_TYPE_BOOLEAN)
    126153            {
     154                dbus_bool_t fSuspend;
    127155                dbus_message_iter_get_basic(&args, &fSuspend);
     156
    128157                /* Trinary operator does not work here as Reason_... is an
    129158                 * anonymous enum. */
     
    133162                    pPowerObj->notify(Reason_HostResume);
    134163            }
     164
    135165            /* The UPowerd interface notifications.  Sleeping is the older one,
    136166             * NotifySleep the newer.  This gives us one second grace before the
     
    142172                || dbus_message_is_signal(pMessage, "org.freedesktop.UPower", "NotifyResume"))
    143173                pPowerObj->notify(Reason_HostResume);
     174
    144175            /* Free local resources held for the message. */
    145176            dbus_message_unref(pMessage);
    146177        }
    147178    }
     179
    148180    /* Close the socket or whatever underlying the connection. */
    149181    dbus_connection_close(pConnection);
     182
    150183    /* Free in-process resources used for the now-closed connection. */
    151184    dbus_connection_unref(pConnection);
     185
    152186    Log(("HostPowerServiceLinux: Exiting thread\n"));
    153187    return VINF_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.

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