winsock2 & wxWidgets: application hangs after reading UDP datagram,then accessing wxTextCtrl

Discussion in 'C++' started by Lars Uffmann, Feb 19, 2008.

  1. Lars Uffmann

    Lars Uffmann Guest

    X-Post to comp.unix.programmer & comp.lang.c++
    F'Up set to comp.lang.c++

    Hi everyone!

    I am sorry that I am not able to reduce the bug-reproducing code
    further, I have been trying to debug this for 2 days at least. What I am
    doing is: I have a minimal wxWidgets application (GUI code as generated
    by wxFormBuilder at the bottom) with a frame mainFrane, a wxBoxSizer
    sizerMain, a wxTextCtrl txt1 and a wxButton cmd1. Now on wxApp::OnInit,
    I start a boost::thread that listens for a UDP datagram. The cmd1 button
    will send a simple UDP packet (just 1 byte, value 0) so the thread can
    finish, then call a join() on the thread to wait for it to exit.

    After that I want to access the properties of the wxTextCtrl txt1. In
    this case txt1->GetValue(). The very function worked fine just before
    the recvfrom call in my thread function. Right AFTER that call, when the
    UDP packet has been received, the program locks up IF I try to access
    txt1->GetValue(). txt1->GetName() works fine just in the line before. If
    I do not call this function, the application is fine and can be exited
    normally. If I do not call recvfrom, I can access txt1->GetValue() just
    fine.

    Now the really strange thing is: if I play back a "REAL" UDP packet,
    like the ones I am writing this application for, everything works just
    fine: the recvfrom gets called, gets (part of) the packet, and then the
    call to txt1->GetValue() yields the expected result, and the application
    is healthy.

    So does this mean that my usage of the socket function sendto(...) is
    wrong, and that it causes undefined behaviour to send a single byte with
    value 0 in a UDP datagram?

    Or if not - what could possibly be causing this lockup? Complete code
    following, sorry for the X-Post, but since it's a problem that occurs
    upon combined usage of the socket library & wxWidgets (and
    boost:thread), I think it makes sense to ask in both relevant groups.
    Unless of course its a winsock2 problem that would not occur with linux
    sockets...

    In the attached code, please search for the comment line that says
    /* LOCKUP HERE */

    To compile this example you'll need wxwidgets, boost::thread and the
    sockets library for your system - if that's not windows (sorry), have to
    adjust the include for winsock2.h

    Best Regards & TIA,

    Lars Uffmann

    code (3 files, latter 2 are output from wxFormBuilder, stripped of
    comments and merged GUI & event handler classes to one file):

    ********** BEGIN debugging.cpp ***********
    #define __USE_W32_SOCKETS
    #include <winsock2.h>

    #define BUFLEN 5120
    #define PORT 6000

    #include <iostream>
    using namespace std;
    #include <sstream>
    #include <boost/thread/thread.hpp>

    #include "wx/wx.h"

    #include "debuggingGUI.h"

    debuggingGUImainFrame *mainWindow;
    boost::thread *THREAD_FileReceiver;

    /* *** */

    void sendEndOfStream()
    {
    struct sockaddr_in saLocalhost;
    SOCKET sEndOfStream;
    int slen = sizeof(saLocalhost);
    char buf[10];

    sEndOfStream = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sEndOfStream == INVALID_SOCKET) {
    cout << "Invalid socket, failed to create socket" << endl;
    return;
    }

    memset((char *) &saLocalhost, 0, sizeof (saLocalhost));
    saLocalhost.sin_family = AF_INET;
    saLocalhost.sin_port = htons(PORT);
    saLocalhost.sin_addr.s_addr = inet_addr ("127.0.0.1");

    buf[0] = 0;
    sendto(sEndOfStream, buf, 1, 0, (sockaddr *) &saLocalhost, slen);
    closesocket (sEndOfStream);
    }

    int listenForAPacket() {
    struct sockaddr_in si_me, si_other;
    SOCKET s;
    int slen = sizeof(si_other);
    char buf[100];
    int nRet;

    s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (s == INVALID_SOCKET) {
    cout << "Invalid socket, failed to create socket" << endl;
    return -2;
    }

    memset((char *) &si_me, 0, sizeof (si_me));
    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORT);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);

    nRet = bind(s, (sockaddr *) &si_me, sizeof (si_me));
    if (nRet == SOCKET_ERROR) {
    cout << "Failed to bind socket" << endl;
    closesocket (s);
    return -2;
    }

    cout << "mainWindow = " << (int) mainWindow << endl;
    cout << mainWindow->txt1->GetValue() << endl;
    recvfrom (s, &buf[0], 10, 0, (sockaddr *) &si_other, &slen);

    cout << "mainWindow = " << (int) mainWindow << endl;
    cout << mainWindow->txt1->GetName() << endl;

    /* LOCKUP HERE */
    cout << mainWindow->txt1->GetValue() << endl;

    closesocket(s);
    return 1;
    }

    /* *** */

    debuggingGUImainFrame::debuggingGUImainFrame( wxWindow* parent )
    :
    mainFrame( parent )
    {
    }

    void debuggingGUImainFrame::OnToggle( wxCommandEvent& event )
    {
    sendEndOfStream();
    cout << "waiting for thread to end" << endl;
    THREAD_FileReceiver->join();
    cout << "thread finished" << endl;
    }


    /* *** */


    class debuggingApp : public wxApp
    {
    virtual bool OnInit();
    };

    DECLARE_APP(debuggingApp)
    IMPLEMENT_APP(debuggingApp)

    bool debuggingApp::OnInit()
    {
    // Initialize WinSock2.2 DLL
    // low-word = major, hi-word = minor
    WSADATA wsaData = {0};
    WORD wVer = MAKEWORD(2,2);

    int nRet = WSAStartup (wVer, &wsaData);
    if (nRet == SOCKET_ERROR) {
    // WSAGetLastError()
    cout << "Failed to init Winsock library" << endl;
    return false;
    }
    mainWindow = new debuggingGUImainFrame((wxFrame *)NULL); //, -1,
    _T("debugging"), wxPoint(50,50), wxSize(450,340) );

    mainWindow->Show (TRUE);
    SetTopWindow (mainWindow);
    THREAD_FileReceiver = new boost::thread(&listenForAPacket);

    return TRUE;
    }
    *********** END debugging.cpp ************

    ********** BEGIN debuggingGUI.h ***********
    #ifndef __debuggingGUI__
    #define __debuggingGUI__

    #include <wx/string.h>
    #include <wx/textctrl.h>
    #include <wx/gdicmn.h>
    #include <wx/font.h>
    #include <wx/colour.h>
    #include <wx/settings.h>
    #include <wx/button.h>
    #include <wx/sizer.h>
    #include <wx/frame.h>

    class mainFrame : public wxFrame
    {
    private:

    protected:
    wxButton* cmd1;
    // Virtual event handlers, overide them in your derived class
    virtual void OnToggle( wxCommandEvent& event ){ event.Skip(); }

    public:
    wxTextCtrl* txt1;
    mainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const
    wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxSize( 500,300 ), long style =
    wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );

    ~mainFrame();
    };

    class debuggingGUImainFrame : public mainFrame
    {
    protected:
    void OnToggle( wxCommandEvent& event );
    public:
    debuggingGUImainFrame( wxWindow* parent );
    };

    #endif //__debuggingGUI__
    *********** END debuggingGUI.h ************

    ********** BEGIN debuggingGUI.cpp ***********
    #include "debuggingGUI.h"

    mainFrame::mainFrame( wxWindow* parent, wxWindowID id, const wxString&
    title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame(
    parent, id, title, pos, size, style )
    {
    this->SetSizeHints( wxDefaultSize, wxDefaultSize );

    wxBoxSizer* sizerMain;
    sizerMain = new wxBoxSizer( wxVERTICAL );

    txt1 = new wxTextCtrl( this, wxID_ANY, wxT("1"), wxDefaultPosition,
    wxDefaultSize, 0 );
    sizerMain->Add( txt1, 0, wxALL, 5 );

    cmd1 = new wxButton( this, wxID_ANY, wxT("toggle"),
    wxDefaultPosition, wxDefaultSize, 0 );
    sizerMain->Add( cmd1, 0, wxALL, 5 );

    this->SetSizer( sizerMain );
    this->Layout();

    // Connect Events
    cmd1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(
    mainFrame::OnToggle ), NULL, this );
    }

    mainFrame::~mainFrame()
    {
    // Disconnect Events
    cmd1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
    wxCommandEventHandler( mainFrame::OnToggle ), NULL, this );
    }
    *********** END debuggingGUI.cpp ************
    Lars Uffmann, Feb 19, 2008
    #1
    1. Advertising

  2. Lars Uffmann

    Guest

    Re: winsock2 & wxWidgets: application hangs after reading UDPdatagram, then accessing wxTextCtrl

    On Feb 19, 10:14 am, Lars Uffmann <> wrote:
    > X-Post to comp.unix.programmer & comp.lang.c++
    > F'Up set to comp.lang.c++
    >
    > Hi everyone!
    >
    > I am sorry that I am not able to reduce the bug-reproducing code
    > further, I have been trying to debug this for 2 days at least. What I am
    > doing is: I have a minimal wxWidgets application (GUI code as generated
    > by wxFormBuilder at the bottom) with a frame mainFrane, a wxBoxSizer
    > sizerMain, a wxTextCtrl txt1 and a wxButton cmd1. Now on wxApp::OnInit,
    > I start a boost::thread that listens for a UDP datagram. The cmd1 button
    > will send a simple UDP packet (just 1 byte, value 0) so the thread can
    > finish, then call a join() on the thread to wait for it to exit.
    >
    > After that I want to access the properties of the wxTextCtrl txt1. In
    > this case txt1->GetValue(). The very function worked fine just before
    > the recvfrom call in my thread function. Right AFTER that call, when the
    > UDP packet has been received, the program locks up IF I try to access
    > txt1->GetValue(). txt1->GetName() works fine just in the line before. If
    > I do not call this function, the application is fine and can be exited
    > normally. If I do not call recvfrom, I can access txt1->GetValue() just
    > fine.
    >
    > Now the really strange thing is: if I play back a "REAL" UDP packet,
    > like the ones I am writing this application for, everything works just
    > fine: the recvfrom gets called, gets (part of) the packet, and then the
    > call to txt1->GetValue() yields the expected result, and the application
    > is healthy.
    >
    > So does this mean that my usage of the socket function sendto(...) is
    > wrong, and that it causes undefined behaviour to send a single byte with
    > value 0 in a UDP datagram?
    >
    > Or if not - what could possibly be causing this lockup? Complete code
    > following, sorry for the X-Post, but since it's a problem that occurs
    > upon combined usage of the socket library & wxWidgets (and
    > boost:thread), I think it makes sense to ask in both relevant groups.
    > Unless of course its a winsock2 problem that would not occur with linux
    > sockets...
    >
    > In the attached code, please search for the comment line that says
    >    /* LOCKUP HERE */
    >
    > To compile this example you'll need wxwidgets, boost::thread and the
    > sockets library for your system - if that's not windows (sorry), have to
    > adjust the include for winsock2.h
    >
    > Best Regards & TIA,
    >
    >     Lars Uffmann
    >
    > code (3 files, latter 2 are output from wxFormBuilder, stripped of
    > comments and merged GUI & event handler classes to one file):
    >
    > ********** BEGIN debugging.cpp ***********
    > #define __USE_W32_SOCKETS
    > #include <winsock2.h>
    >
    > #define BUFLEN 5120
    > #define PORT 6000
    >
    > #include <iostream>
    > using namespace std;
    > #include <sstream>
    > #include <boost/thread/thread.hpp>
    >
    > #include "wx/wx.h"
    >
    > #include "debuggingGUI.h"
    >
    > debuggingGUImainFrame *mainWindow;
    > boost::thread *THREAD_FileReceiver;
    >
    > /* *** */
    >
    > void sendEndOfStream()
    > {
    >    struct sockaddr_in saLocalhost;
    >    SOCKET sEndOfStream;
    >    int slen = sizeof(saLocalhost);
    >    char buf[10];
    >
    >    sEndOfStream = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    >    if (sEndOfStream == INVALID_SOCKET) {
    >      cout << "Invalid socket, failed to create socket" << endl;
    > return;
    >    }
    >
    >    memset((char *) &saLocalhost, 0, sizeof (saLocalhost));
    >    saLocalhost.sin_family = AF_INET;
    >    saLocalhost.sin_port = htons(PORT);
    >    saLocalhost.sin_addr.s_addr = inet_addr ("127.0.0.1");
    >
    >    buf[0] = 0;
    >    sendto(sEndOfStream, buf, 1, 0, (sockaddr *) &saLocalhost, slen);
    >    closesocket (sEndOfStream);
    >
    > }
    >
    > int listenForAPacket() {
    >    struct sockaddr_in si_me, si_other;
    >    SOCKET s;
    >    int slen = sizeof(si_other);
    >    char buf[100];
    >    int nRet;
    >
    >    s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    >    if (s == INVALID_SOCKET) {
    >      cout << "Invalid socket, failed to create socket" << endl;
    > return -2;
    >    }
    >
    >    memset((char *) &si_me, 0, sizeof (si_me));
    >    si_me.sin_family = AF_INET;
    >    si_me.sin_port = htons(PORT);
    >    si_me.sin_addr.s_addr = htonl(INADDR_ANY);
    >
    >    nRet = bind(s, (sockaddr *) &si_me, sizeof (si_me));
    >    if (nRet == SOCKET_ERROR) {
    >      cout << "Failed to bind socket" << endl;
    >      closesocket (s);
    > return -2;
    >    }
    >
    >    cout << "mainWindow = " << (int) mainWindow << endl;
    >    cout << mainWindow->txt1->GetValue() << endl;
    >    recvfrom (s, &buf[0], 10, 0, (sockaddr *) &si_other, &slen);
    >
    >    cout << "mainWindow = " << (int) mainWindow << endl;
    >    cout << mainWindow->txt1->GetName() << endl;
    >
    >    /* LOCKUP HERE */
    >    cout << mainWindow->txt1->GetValue() << endl;
    >
    >    closesocket(s);
    >    return 1;
    >
    > }
    >
    > /* *** */
    >
    > debuggingGUImainFrame::debuggingGUImainFrame( wxWindow* parent )
    > :
    > mainFrame( parent )
    > {
    >
    > }
    >
    > void debuggingGUImainFrame::OnToggle( wxCommandEvent& event )
    > {
    >    sendEndOfStream();
    > cout << "waiting for thread to end" << endl;
    >    THREAD_FileReceiver->join();
    > cout << "thread finished" << endl;
    >
    > }
    >
    > /* *** */
    >
    > class debuggingApp : public wxApp
    > {
    >    virtual bool OnInit();
    >
    > };
    >
    > DECLARE_APP(debuggingApp)
    > IMPLEMENT_APP(debuggingApp)
    >
    > bool debuggingApp::OnInit()
    > {
    >    // Initialize WinSock2.2 DLL
    >    // low-word = major, hi-word = minor
    >    WSADATA wsaData = {0};
    >    WORD wVer = MAKEWORD(2,2);
    >
    >    int nRet = WSAStartup (wVer, &wsaData);
    >    if (nRet == SOCKET_ERROR) {
    >      // WSAGetLastError()
    >      cout << "Failed to init Winsock library" << endl;
    > return false;
    >    }
    >    mainWindow = new debuggingGUImainFrame((wxFrame *)NULL); //, -1,
    > _T("debugging"), wxPoint(50,50), wxSize(450,340) );
    >
    >    mainWindow->Show (TRUE);
    >    SetTopWindow (mainWindow);
    >    THREAD_FileReceiver = new boost::thread(&listenForAPacket);
    >
    >    return TRUE;}
    >
    > *********** END debugging.cpp ************
    >
    > ********** BEGIN debuggingGUI.h ***********
    > #ifndef __debuggingGUI__
    > #define __debuggingGUI__
    >
    > #include <wx/string.h>
    > #include <wx/textctrl.h>
    > #include <wx/gdicmn.h>
    > #include <wx/font.h>
    > #include <wx/colour.h>
    > #include <wx/settings.h>
    > #include <wx/button.h>
    > #include <wx/sizer.h>
    > #include <wx/frame.h>
    >
    > class mainFrame : public wxFrame
    > {
    >    private:
    >
    >    protected:
    >      wxButton* cmd1;
    >      // Virtual event handlers, overide them in your derived class
    >      virtual void OnToggle( wxCommandEvent& event ){ event.Skip(); }
    >
    >    public:
    >      wxTextCtrl* txt1;
    >      mainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const
    > wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition,
    > const wxSize& size = wxSize( 500,300 ), long style =
    > wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
    >
    >      ~mainFrame();
    >
    > };
    >
    > class debuggingGUImainFrame : public mainFrame
    > {
    > protected:
    >         void OnToggle( wxCommandEvent& event );
    > public:
    >         debuggingGUImainFrame( wxWindow* parent );
    >
    > };
    >
    > #endif //__debuggingGUI__
    > *********** END debuggingGUI.h ************
    >
    > ********** BEGIN debuggingGUI.cpp ***********
    > #include "debuggingGUI.h"
    >
    > mainFrame::mainFrame( wxWindow* parent, wxWindowID id, const wxString&
    > title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame(
    > parent, id, title, pos, size, style )
    > {
    >    this->SetSizeHints( wxDefaultSize, wxDefaultSize );
    >
    >    wxBoxSizer* sizerMain;
    >    sizerMain = new wxBoxSizer( wxVERTICAL );
    >
    >    txt1 = new wxTextCtrl( this, wxID_ANY, wxT("1"), wxDefaultPosition,
    > wxDefaultSize, 0 );
    >    sizerMain->Add( txt1, 0, wxALL, 5 );
    >
    >    cmd1 = new wxButton( this, wxID_ANY, wxT("toggle"),
    > wxDefaultPosition, wxDefaultSize, 0 );
    >    sizerMain->Add( cmd1, 0, wxALL, 5 );
    >
    >    this->SetSizer( sizerMain );
    >    this->Layout();
    >
    >    // Connect Events
    >    cmd1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(
    > mainFrame::OnToggle ), NULL, this );
    >
    > }
    >
    > mainFrame::~mainFrame()
    > {
    >    // Disconnect Events
    >    cmd1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
    > wxCommandEventHandler( mainFrame::OnToggle ), NULL, this );}
    >
    > *********** END debuggingGUI.cpp ************


    wxWidgets and sockets are OT in this newsgroup.
    , Feb 19, 2008
    #2
    1. Advertising

  3. Lars Uffmann

    Lars Uffmann Guest

    Re: winsock2 & wxWidgets: application hangs after reading UDPdatagram, then accessing wxTextCtrl

    wrote:
    > wxWidgets and sockets are OT in this newsgroup.


    That is a matter of perspective, especially when the bug is somewhere in
    between and might also involve boost::thread usage.

    However, a fullquote followed by a single line of a useless "smart"
    remark is always OT.

    ....

    Lars
    Lars Uffmann, Feb 19, 2008
    #3
  4. Lars Uffmann

    Guest

    Re: winsock2 & wxWidgets: application hangs after reading UDPdatagram, then accessing wxTextCtrl

    On Feb 19, 10:44 am, Lars Uffmann <> wrote:
    > wrote:
    > > wxWidgets and sockets are OT in this newsgroup.

    >
    > That is a matter of perspective, especially when the bug is somewhere in
    > between and might also involve boost::thread usage.
    >
    > However, a fullquote followed by a single line of a useless "smart"
    > remark is always OT.
    >
    > ...
    >
    >    Lars


    My news reader does the quoting for me automagically. But don't
    worry, you will get used to it.
    , Feb 19, 2008
    #4
  5. Lars Uffmann

    red floyd Guest

    Re: winsock2 & wxWidgets: application hangs after reading UDP datagram,then accessing wxTextCtrl

    wrote:
    > On Feb 19, 10:44 am, Lars Uffmann <> wrote:
    >> wrote:

    [redacted]
    >>
    >> However, a fullquote followed by a single line of a useless "smart"
    >> remark is always OT.
    >>
    >> ...
    >>
    >> Lars

    >
    > My news reader does the quoting for me automagically. But don't
    > worry, you will get used to it.


    Wrong. *YOU* will get used to the etiquette of this newsgroup.

    http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.4

    And, great, your newsreader quotes the whole post. So what, so does
    mine. I edit it before posting. You can do the same.
    red floyd, Feb 19, 2008
    #5
  6. Re: winsock2 & wxWidgets: application hangs after reading UDPdatagram, then accessing wxTextCtrl

    On Feb 19, 7:14 am, Lars Uffmann <> wrote:

    > I am sorry that I am not able to reduce the bug-reproducing code
    > further, I have been trying to debug this for 2 days at least. What I am
    > doing is: I have a minimal wxWidgets application (GUI code as generated
    > by wxFormBuilder at the bottom) with a frame mainFrane, a wxBoxSizer
    > sizerMain, a wxTextCtrl txt1 and a wxButton cmd1. Now on wxApp::OnInit,
    > I start a boost::thread that listens for a UDP datagram. The cmd1 button
    > will send a simple UDP packet (just 1 byte, value 0) so the thread can
    > finish, then call a join() on the thread to wait for it to exit.


    UDP is unreliable. If the datagram is dropped/lost, the thread will
    not exit. Some platforms do offer reliable local UDP, but the platform
    you are using may not.

    > After that I want to access the properties of the wxTextCtrl txt1. In
    > this case txt1->GetValue(). The very function worked fine just before
    > the recvfrom call in my thread function. Right AFTER that call, when the
    > UDP packet has been received, the program locks up IF I try to access
    > txt1->GetValue(). txt1->GetName() works fine just in the line before. If
    > I do not call this function, the application is fine and can be exited
    > normally. If I do not call recvfrom, I can access txt1->GetValue() just
    > fine.


    Perhaps the thread that sends the datagram does something to 'txtl'?

    > Now the really strange thing is: if I play back a "REAL" UDP packet,
    > like the ones I am writing this application for, everything works just
    > fine: the recvfrom gets called, gets (part of) the packet, and then the
    > call to txt1->GetValue() yields the expected result, and the application
    > is healthy.


    That definitely sounds like the problem is something else the thread
    that sends the UDP datagram does.

    [snip]

    I think your problem is this:

    1) Call the thread that sends the datagram thread A. It sends the
    datagram and then blocks waiting for thread B to terminate. This
    thread is operating from the frame, so it holds a lock on the frame.

    2) Thread B gets the datagram and tries to access 'txtl'. The problem
    is that thread A holds a lock on the frame. So thread B must wait
    until thread A releases the lock.

    At this point, thread A is waiting for thread B to finish, but thread
    B cannot finish until it gets the frame lock, but thread A holds the
    frame lock.

    DS
    David Schwartz, Feb 20, 2008
    #6
  7. Lars Uffmann

    Lars Uffmann Guest

    Re: winsock2 & wxWidgets: application hangs after reading UDPdatagram, then accessing wxTextCtrl

    Hi David,

    David Schwartz wrote:
    > UDP is unreliable. If the datagram is dropped/lost, the thread will
    > not exit. Some platforms do offer reliable local UDP, but the platform
    > you are using may not.


    The datagram is definitely arriving, my code is doing a cout to verify
    it has reached the step after recvfrom :)

    > Perhaps the thread that sends the datagram does something to 'txtl'?

    Well - the _thread_ sending the datagram is the main wxWindows thread
    (event handler), but the function sending the datagram isn't doing
    anything to txt1.

    > I think your problem is this:
    > [...]
    > At this point, thread A is waiting for thread B to finish, but thread
    > B cannot finish until it gets the frame lock, but thread A holds the
    > frame lock.


    Wow. Very nice analysis. This might indeed be the problem here. It
    definitely gave me a new insight into the situation. And it would
    explain the difference between receiving a "selfmade" UDP packet
    (because only then thread A is waiting for thread B) and the played back
    packets.

    Thank you very much, I think I'll be able to work around this now (got
    pointed to custom events in wxwindows newsgroup).

    Best Regards,

    Lars
    Lars Uffmann, Feb 20, 2008
    #7
  8. Lars Uffmann

    Lars Uffmann Guest

    David,

    David Schwartz wrote:
    > I think your problem is this:
    >
    > 1) Call the thread that sends the datagram thread A. It sends the
    > datagram and then blocks waiting for thread B to terminate. This
    > thread is operating from the frame, so it holds a lock on the frame.
    >
    > 2) Thread B gets the datagram and tries to access 'txtl'. The problem
    > is that thread A holds a lock on the frame. So thread B must wait
    > until thread A releases the lock.
    >
    > At this point, thread A is waiting for thread B to finish, but thread
    > B cannot finish until it gets the frame lock, but thread A holds the
    > frame lock.



    After some further testing, I have pinpointed the problem, and it was
    exactly what you said. The following (reduced) example proves that the
    whole thing isn't even related to the socket library, but solely happens
    to do the mentioned frame lock. Thanks a lot! Now I need to find a way
    around this :)

    Best Regards,

    Lars

    *** code from here ***
    #include <iostream>
    using namespace std;
    #include <boost/thread/thread.hpp>

    #include "wx/wx.h"
    #include <wx/string.h>
    #include <wx/textctrl.h>
    #include <wx/gdicmn.h>
    #include <wx/font.h>
    #include <wx/colour.h>
    #include <wx/settings.h>
    #include <wx/button.h>
    #include <wx/sizer.h>
    #include <wx/frame.h>

    class mainFrame : public wxFrame
    {
    protected:
    // Virtual event handlers, overide them in your derived class
    virtual void OnToggle( wxCommandEvent& event ){ event.Skip(); }

    public:
    wxButton* cmd1;
    wxTextCtrl* txt1;
    mainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString&
    title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const
    wxSize& size = wxSize( 500,300 ), long style =
    wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
    ~mainFrame();
    };

    class debuggingGUImainFrame : public mainFrame
    {
    protected:
    void OnToggle( wxCommandEvent& event );

    public:
    debuggingGUImainFrame( wxWindow* parent );
    };


    mainFrame::mainFrame( wxWindow* parent, wxWindowID id, const wxString&
    title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame(
    parent, id, title, pos, size, style )
    {
    this->SetSizeHints( wxDefaultSize, wxDefaultSize );

    wxBoxSizer* sizerMain;
    sizerMain = new wxBoxSizer( wxVERTICAL );

    txt1 = new wxTextCtrl( this, wxID_ANY, wxT("1"), wxDefaultPosition,
    wxDefaultSize, 0 );
    sizerMain->Add( txt1, 0, wxALL, 5 );

    cmd1 = new wxButton( this, wxID_ANY, wxT("toggle"), wxDefaultPosition,
    wxDefaultSize, 0 );
    sizerMain->Add( cmd1, 0, wxALL, 5 );

    this->SetSizer( sizerMain );
    this->Layout();

    // Connect Events
    cmd1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(
    mainFrame::OnToggle ), NULL, this );
    }

    mainFrame::~mainFrame()
    {
    // Disconnect Events
    cmd1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(
    mainFrame::OnToggle ), NULL, this );
    }

    /* *** */

    debuggingGUImainFrame *mainWindow;
    boost::thread *myThread;

    /* *** */

    void demonstrateFrameLock()
    {
    sleep (1);
    cout << "child thread: taking a nap (2 seconds)" << endl;
    sleep (2);
    cout << "child thread: woke up!" << endl;

    cout << "child thread: mainWindow->txt1->GetValue = " <<
    mainWindow->txt1->GetValue() << endl;
    cout << "child thread: thread finished" << endl;
    }

    /* *** */

    debuggingGUImainFrame::debuggingGUImainFrame( wxWindow* parent )
    :
    mainFrame( parent )
    {
    }

    void debuggingGUImainFrame::OnToggle( wxCommandEvent& event )
    {
    myThread = new boost::thread(&demonstrateFrameLock);
    cout << "main thread: sleeping 5 seconds" << endl;
    sleep (5);
    cout << "main thread: done sleeping" << endl;

    // cout << "main thread: waiting for child thread to end" << endl;
    // myThread->join();

    delete myThread;
    myThread = 0;

    cout << "main thread: thread finished" << endl;
    }

    /* *** */


    class debuggingApp : public wxApp
    {
    virtual bool OnInit();
    };

    DECLARE_APP(debuggingApp)
    IMPLEMENT_APP(debuggingApp)

    bool debuggingApp::OnInit()
    {
    mainWindow = new debuggingGUImainFrame((wxFrame *)NULL); //, -1,
    _T("debugging"), wxPoint(50,50), wxSize(450,340) );

    mainWindow->Show (TRUE);
    SetTopWindow (mainWindow);

    return TRUE;
    }
    Lars Uffmann, Feb 21, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Javayang
    Replies:
    1
    Views:
    1,110
    Steve Horsley
    Sep 11, 2003
  2. Jonas Hei
    Replies:
    1
    Views:
    873
    Darryl L. Pierce
    Jun 14, 2004
  3. Replies:
    2
    Views:
    2,977
    David Van de Voorde
    Jan 21, 2005
  4. -
    Replies:
    11
    Views:
    1,650
    Gordon Beaton
    Aug 26, 2005
  5. Iain King

    UDP max datagram size

    Iain King, Apr 12, 2006, in forum: Python
    Replies:
    6
    Views:
    14,069
    =?iso-8859-1?q?Luis_M._Gonz=E1lez?=
    Apr 13, 2006
Loading...

Share This Page