VirtualBox

Changeset 9206

Show
Ignore:
Timestamp:
05/28/08 19:50:02 (6 months ago)
Author:
vboxsync
Message:

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

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 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 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy