VirtualBox

Changeset 9206 in vbox for trunk


Ignore:
Timestamp:
May 28, 2008 5:50:02 PM (17 years ago)
Author:
vboxsync
Message:

Fixed the console crash: setFocus was called from the console thread.

Location:
trunk/src/VBox/Debugger
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/VBoxDbgBase.cpp

    r8155 r9206  
    3030
    3131
    32 VBoxDbgBase::VBoxDbgBase(PVM pVM) : m_pVM(pVM)
     32VBoxDbgBase::VBoxDbgBase(PVM pVM) : m_pVM(pVM), m_hGUIThread(RTThreadNativeSelf())
    3333{
    3434    /*
  • trunk/src/VBox/Debugger/VBoxDbgBase.h

    r8155 r9206  
    2828#include <VBox/vmapi.h>
    2929#include <VBox/dbg.h>
     30#include <iprt/thread.h>
    3031
    3132
     
    6162    {
    6263        return m_pVM != NULL;
     64    }
     65
     66    /**
     67     * Checks if the current thread is the GUI thread or not.
     68     * @return true/false accordingly.
     69     */
     70    bool isGUIThread() const
     71    {
     72        return m_hGUIThread == RTThreadNativeSelf();
    6373    }
    6474
     
    107117    /** The VM handle. */
    108118    PVM m_pVM;
     119    /** The handle of the GUI thread. */
     120    RTNATIVETHREAD m_hGUIThread;
    109121};
    110122
  • trunk/src/VBox/Debugger/VBoxDbgConsole.cpp

    r8155 r9206  
    5858
    5959VBoxDbgConsoleOutput::VBoxDbgConsoleOutput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
    60     : QTextEdit(pParent, pszName), m_uCurLine(0), m_uCurPos(0)
     60    : QTextEdit(pParent, pszName), m_uCurLine(0), m_uCurPos(0), m_hGUIThread(RTThreadNativeSelf())
    6161{
    6262    setReadOnly(true);
     
    6969    Font.setFamily("Courier [Monotype]");
    7070    setFont(Font);
     71
     72    /* green on black */
     73    setPaper(QBrush(Qt::black));
     74    //setColor(Qt::green);
     75    setColor(QColor(qRgb(0, 0xe0, 0)));
    7176}
    7277
    7378VBoxDbgConsoleOutput::~VBoxDbgConsoleOutput()
    7479{
     80    Assert(m_hGUIThread == RTThreadNativeSelf());
    7581}
    7682
    7783void VBoxDbgConsoleOutput::appendText(const QString &rStr)
    7884{
     85    Assert(m_hGUIThread == RTThreadNativeSelf());
     86
    7987    if (rStr.isEmpty() || rStr.isNull() || !rStr.length())
    8088        return;
     
    128136
    129137VBoxDbgConsoleInput::VBoxDbgConsoleInput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
    130     : QComboBox(true, pParent, pszName), m_iBlankItem(0)
     138    : QComboBox(true, pParent, pszName), m_iBlankItem(0), m_hGUIThread(RTThreadNativeSelf())
    131139{
    132140    insertItem("", m_iBlankItem);
     
    141149VBoxDbgConsoleInput::~VBoxDbgConsoleInput()
    142150{
     151    Assert(m_hGUIThread == RTThreadNativeSelf());
    143152}
    144153
    145154void VBoxDbgConsoleInput::setLineEdit(QLineEdit *pEdit)
    146155{
     156    Assert(m_hGUIThread == RTThreadNativeSelf());
    147157    QComboBox::setLineEdit(pEdit);
    148158    if (lineEdit() == pEdit && pEdit)
     
    152162void VBoxDbgConsoleInput::returnPressed()
    153163{
     164    Assert(m_hGUIThread == RTThreadNativeSelf());
    154165    /* deal with the current command. */
    155166    QString Str = currentText();
     
    187198    m_pszInputBuf(NULL), m_cbInputBuf(0), m_cbInputBufAlloc(0),
    188199    m_pszOutputBuf(NULL), m_cbOutputBuf(0), m_cbOutputBufAlloc(0),
    189     m_Timer(), m_fUpdatePending(false), m_Thread(NIL_RTTHREAD), m_EventSem(NIL_RTSEMEVENT), m_fTerminate(false)
     200    m_pTimer(NULL), m_fUpdatePending(false), m_Thread(NIL_RTTHREAD), m_EventSem(NIL_RTSEMEVENT), m_fTerminate(false)
    190201{
    191202    setCaption("VBoxDbg - Console");
     
    227238
    228239    /*
     240     * Setup the timer.
     241     */
     242    m_pTimer = new QTimer(this);
     243    connect(m_pTimer, SIGNAL(timeout()), SLOT(updateOutput()));
     244
     245    /*
    229246     * Init the backend structure.
    230247     */
     
    251268VBoxDbgConsole::~VBoxDbgConsole()
    252269{
     270    Assert(isGUIThread());
     271
    253272    /*
    254273     * Wait for the thread.
     
    266285     * Free resources.
    267286     */
     287    delete m_pTimer;
     288    m_pTimer = NULL;
    268289    RTCritSectDelete(&m_Lock);
    269290    RTSemEventDestroy(m_EventSem);
     
    282303void VBoxDbgConsole::commandSubmitted(const QString &rCommand)
    283304{
     305    Assert(isGUIThread());
     306
    284307    lock();
    285308    RTSemEventSignal(m_EventSem);
     
    322345void VBoxDbgConsole::updateOutput()
    323346{
     347    Assert(isGUIThread());
     348
    324349    lock();
    325350    m_fUpdatePending = false;
     
    368393    /* dirty focus hack: */
    369394    if (pThis->m_fInputRestoreFocus)
    370     {
    371         pThis->m_fInputRestoreFocus = false;
    372         if (!pThis->m_pInput->hasFocus())
    373             pThis->m_pInput->setFocus();
    374     }
     395        QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kInputRestoreFocus));
    375396
    376397    bool fRc = true;
     
    476497     */
    477498    if (!pThis->m_fUpdatePending)
    478         QApplication::postEvent(pThis, new QCustomEvent(QEvent::User, NULL));
     499        QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kUpdate));
    479500
    480501    pThis->unlock();
     
    503524    LogFlow(("backThread: returns %Vrc\n", rc));
    504525    if (!pThis->m_fTerminate)
    505         QApplication::postEvent(pThis, new QCustomEvent(QEvent::User, (void *)1));
     526        QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kTerminated));
    506527    return rc;
    507528}
    508529
    509 void VBoxDbgConsole::customEvent(QCustomEvent *pEvent)
    510 {
    511     if (pEvent->type() == QEvent::User)
    512     {
    513         uintptr_t u = (uintptr_t)pEvent->data(); /** @todo enum! */
    514         switch (u)
     530bool VBoxDbgConsole::event(QEvent *pGenEvent)
     531{
     532    Assert(isGUIThread());
     533    if (pGenEvent->type() == (QEvent::Type)VBoxDbgConsoleEvent::kEventNumber)
     534    {
     535        VBoxDbgConsoleEvent *pEvent = (VBoxDbgConsoleEvent *)pGenEvent;
     536
     537        switch (pEvent->command())
    515538        {
    516539            /* make update pending. */
    517             case 0:
     540            case VBoxDbgConsoleEvent::kUpdate:
    518541                if (!m_fUpdatePending)
    519542                {
    520543                    m_fUpdatePending = true;
    521                     m_Timer.singleShot(10, this, SLOT(updateOutput()));
     544                    m_pTimer->start(10, true /* single shot */);
    522545                }
    523546                break;
    524547
     548            /* dirty hack: restores the focus */
     549            case VBoxDbgConsoleEvent::kInputRestoreFocus:
     550                if (m_fInputRestoreFocus)
     551                {
     552                    m_fInputRestoreFocus = false;
     553                    if (!m_pInput->hasFocus())
     554                        m_pInput->setFocus();
     555                }
     556                break;
     557
    525558            /* the thread terminated */
    526             case 1:
     559            case VBoxDbgConsoleEvent::kTerminated:
    527560                m_pInput->setEnabled(false);
    528561                break;
     
    530563            /* paranoia */
    531564            default:
    532                 AssertMsgFailed(("u=%d\n", u));
     565                AssertMsgFailed(("command=%d\n", pEvent->command()));
    533566                break;
    534567        }
    535     }
    536 }
    537 
     568        return true;
     569    }
     570
     571    return QVBox::event(pGenEvent);
     572}
     573
  • trunk/src/VBox/Debugger/VBoxDbgConsole.h

    r8155 r9206  
    3232#include <iprt/critsect.h>
    3333#include <iprt/semaphore.h>
     34#include <iprt/thread.h>
    3435
    3536
     
    6667    /** The position in the current line. */
    6768    unsigned m_uCurPos;
     69    /** The handle to the GUI thread. */
     70    RTNATIVETHREAD m_hGUIThread;
    6871};
    6972
     
    118121    /** The current blank entry. */
    119122    int m_iBlankItem;
     123    /** The handle to the GUI thread. */
     124    RTNATIVETHREAD m_hGUIThread;
    120125};
    121126
     
    224229protected:
    225230    /**
    226      * Use to get the GUI thread to insert the output data.
    227      */
    228     void customEvent(QCustomEvent *pEvent);
     231     * Processes GUI command posted by the console thread.
     232     *
     233     * Qt3 isn't thread safe on any platform, meaning there is no locking, so, as
     234     * a result we have to be very careful. All operations on objects which we share
     235     * with the main thread has to be posted to it so it can perform it.
     236     */
     237    bool event(QEvent *pEvent);
    229238
    230239protected:
     
    249258    size_t m_cbOutputBufAlloc;
    250259    /** The timer object used to process output in a delayed fashion. */
    251     QTimer m_Timer;
     260    QTimer *m_pTimer;
    252261    /** Set when an output update is pending. */
    253262    bool volatile m_fUpdatePending;
     
    278287
    279288
     289/**
     290 * Simple event class for push certain operations over
     291 * onto the GUI thread.
     292 */
     293class VBoxDbgConsoleEvent : public QEvent
     294{
     295public:
     296    typedef enum  { kUpdate, kInputRestoreFocus, kTerminated } VBoxDbgConsoleEventType;
     297    enum { kEventNumber = QEvent::User + 42 };
     298
     299    VBoxDbgConsoleEvent(VBoxDbgConsoleEventType enmCommand)
     300        : QEvent((QEvent::Type)kEventNumber), m_enmCommand(enmCommand)
     301    {
     302    }
     303
     304    VBoxDbgConsoleEventType command() const
     305    {
     306        return m_enmCommand;
     307    }
     308
     309private:
     310    VBoxDbgConsoleEventType m_enmCommand;
     311};
     312
     313
    280314#endif
     315
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