wxTCP... and recursive Yield Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
cesco79
In need of some credit
In need of some credit
Posts: 3
Joined: Sun May 07, 2006 10:16 pm

wxTCP... and recursive Yield

Post by cesco79 » Sun May 07, 2006 10:40 pm

Hi all!
I'm writing an app (on Win32) that is divided into two different programs.

The first must run likes a service: it communicate with an external electronic equipment through serial line and shows only an icon on the tray in order to signal the communication state.

The second is GUI based and shows the data read on the serial line by the first app. Multiple instance of this app should run together on a windows terminal services server.

So i need to implement an IPC solution to make multiple copies of the second app comunicate with the first.

I have first tried wxSocket and then wxTCP... but with both the server side die with the assert "wxYield called recursively" when I open a second copy of the GUI app.
The strange things is that if I use wxDDE... all works well but sadly I can't use it because it does not work through different user account... :(

Any suggestion will be very appreciated!!
Thanks very much,
Francesco

Following is my server side code:

Code: Select all

class myConnection : public wxTCPConnection {
public:
	myConnection() : wxConnection {};

	virtual wxChar *OnRequest(const wxString& topic, const wxString& item, int *size, wxIPCFormat format);
    virtual bool OnPoke(const wxString& topic, const wxString& item, wxChar *data, int size, wxIPCFormat format);

protected:
	BYTE bufferTX[10000];
	BYTE bufferRX[10000];

private:
  
  int InviaMsgStato9910();
  int InviaMsgStato9130();
  int InviaInformazioniSw();
  int InviaInformazioniDistinte();
  
  void RiceviModificaDistinta();
  void RiceviRicettaManuale();
};

class SerialServer : wxTCPServer {
public: 
	SerialServer() { m_connection= NULL; }
	~SerialServer() {  
                if (m_connection) 
                        m_connection = NULL;
        }
	bool IsConnected() { return m_connection != NULL; };
	myConnection *GetConnection() { return m_connection; };
	wxConnectionBase *OnAcceptConnection(const wxString& topic) {
  	       if ( topic == "Tecna_DDE_Client" )
               {
                       m_connection = new CConnection();
                       return m_connection;
               }
               return NULL;
        }

        protected:
	        myConnection     *m_connection;
};

bool myConnection::OnPoke(const wxString& topic,
    const wxString& item, wxChar *data, int size, wxIPCFormat format)
{
	memcpy(&bufferRX[0], (void*)data, size);
	if (item == "MOD_DISTINTA") 
			RiceviModificaDistinta();
	else if (item == "MOD_RICETTA") 
			RiceviRicettaManuale();
			
	return wxConnection::OnPoke(topic, item, data, size, format);
}

wxChar *myConnection::OnRequest(const wxString& topic,
    const wxString& item, int * size, wxIPCFormat format)
{
    int i;
    wxString num;
    if (item == "INFO_SW")
		*size = InviaInformazioniSw();
	else if (item.Left(6) == "STATOB") 
		*size = InviaMsgStato9910(); 
	else if (item.Left(6) == "STATOE") 
		*size = InviaMsgStato9130(); 
	else if (item.Left(4) == "DIST")
		*size = InviaInformazioniDistinte();
	else
		*size = 0;
	dentro = false;
    return (char*)&bufferTX[0];
}


lowjoel
Moderator
Moderator
Posts: 1511
Joined: Sun Jun 19, 2005 11:37 am
Location: Singapore
Contact:

Post by lowjoel » Tue May 09, 2006 11:04 pm

Look at http://wiki.wxwidgets.org/docbrowse.cgi ... wxappyield

"Calling Yield() recursively is normally an error and an assert failure is raised in debug build if such situation is detected. However if the onlyIfNeeded parameter is true, the method will just silently return false instead."

HTH,
Joel

sago
Earned a small fee
Earned a small fee
Posts: 18
Joined: Tue Oct 21, 2008 7:59 am

Post by sago » Tue Oct 28, 2008 2:58 pm

Hi!

I have the same problem with wxTCP, and understand it more or less.
But what is the solution ?

sago
Earned a small fee
Earned a small fee
Posts: 18
Joined: Tue Oct 21, 2008 7:59 am

Create a thread for each socket

Post by sago » Wed Oct 29, 2008 2:23 pm

Here http://forums.wxwidgets.org/viewtopic.p ... ht=wxyield, it is said I can create a thread for each socket; so I think that it is a thread for each wxTCPConnection for me..

But I am not sure how to do that. I have a class MyServer derived from wxTCPServer and a class MyConnection derived from wxTCPConnection. I have to derive the class MyConnection also from wxThread ? Or I must create a class derived from wxThread which have a MyConnection object ? Finally, Must I do the same thing for the class MyServer ? Because otherwise, if I've understood the problem, in the case of the connection of 2 clients in the same time, the assert "wxYield called recursively" will appear !

Thx

sago
Earned a small fee
Earned a small fee
Posts: 18
Joined: Tue Oct 21, 2008 7:59 am

Post by sago » Wed Oct 29, 2008 2:29 pm

lowjoel wrote:Look at http://wiki.wxwidgets.org/docbrowse.cgi ... wxappyield

"Calling Yield() recursively is normally an error and an assert failure is raised in debug build if such situation is detected. However if the onlyIfNeeded parameter is true, the method will just silently return false instead."

HTH,
Joel
The function "Yield(/*default: false*/)" is called in the socket class which is used by wxTCP.. classes. You suggest to modify the library by using "Yield(true)" ?

sago
Earned a small fee
Earned a small fee
Posts: 18
Joined: Tue Oct 21, 2008 7:59 am

Post by sago » Fri Nov 07, 2008 11:55 am

sago wrote:
lowjoel wrote:Look at http://wiki.wxwidgets.org/docbrowse.cgi ... wxappyield

"Calling Yield() recursively is normally an error and an assert failure is raised in debug build if such situation is detected. However if the onlyIfNeeded parameter is true, the method will just silently return false instead."

HTH,
Joel
The function "Yield(/*default: false*/)" is called in the socket class which is used by wxTCP.. classes. You suggest to modify the library by using "Yield(true)" ?
I do it, but now the windows freezes instead of having the assert.

feelthat
Knows some wx things
Knows some wx things
Posts: 30
Joined: Tue Oct 05, 2010 3:42 pm

wxsocket DLL plugin loop bug

Post by feelthat » Fri Dec 31, 2010 10:03 am

2.8.11 fixed

wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
{
int total;

// Try the pushback buffer first
total = GetPushback(buffer, nbytes, false);
nbytes -= total;
buffer = (char *)buffer + total;

// Return now in one of the following cases:
// - the socket is invalid,
// - we got all the data
if ( !m_socket ||
!nbytes )
return total;

// Possible combinations (they are checked in this order)
// wxSOCKET_NOWAIT
// wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
// wxSOCKET_BLOCK
// wxSOCKET_NONE
//
int ret;
if (m_flags & wxSOCKET_NOWAIT)
{
m_socket->SetNonBlocking(1);
ret = m_socket->Read((char *)buffer, nbytes);
m_socket->SetNonBlocking(0);

if (ret > 0)
total += ret;
}
else
{
/*bool more = true;

while (more)
{
if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
break;

ret = m_socket->Read((char *)buffer, nbytes);

if (ret > 0)
{
total += ret;
nbytes -= ret;
buffer = (char *)buffer + ret;
}

// If we got here and wxSOCKET_WAITALL is not set, we can leave
// now. Otherwise, wait until we recv all the data or until there
// is an error.
//
more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
}*/

bool more = true;

int time_left;
long timeout = m_timeout * 1000;
wxDateTime current_time = wxDateTime::UNow();
unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout;

while (more)
{
current_time = wxDateTime::UNow();
time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond());
if ((!timeout) || (time_left <= 0))
break;

ret = m_socket->Read((char *)buffer, nbytes);

if (ret > 0)
{
total += ret;
nbytes -= ret;
buffer = (char *)buffer + ret;
}

// If we got here and wxSOCKET_WAITALL is not set, we can leave
// now. Otherwise, wait until we recv all the data or until there
// is an error.
//
more = nbytes > 0;
}
}

return total;
}

//////////////////////////////////

wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
{
wxUint32 total = 0;

// If the socket is invalid or parameters are ill, return immediately
if (!m_socket || !buffer || !nbytes)
return 0;

// Possible combinations (they are checked in this order)
// wxSOCKET_NOWAIT
// wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
// wxSOCKET_BLOCK
// wxSOCKET_NONE
//
int ret;
if (m_flags & wxSOCKET_NOWAIT)
{
m_socket->SetNonBlocking(1);
ret = m_socket->Write((const char *)buffer, nbytes);
m_socket->SetNonBlocking(0);

if (ret > 0)
total = ret;
}
else
{
/*bool more = true;

while (more)
{
if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
break;

ret = m_socket->Write((const char *)buffer, nbytes);

if (ret > 0)
{
total += ret;
nbytes -= ret;
buffer = (const char *)buffer + ret;
}

// If we got here and wxSOCKET_WAITALL is not set, we can leave
// now. Otherwise, wait until we send all the data or until there
// is an error.
//
more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
}*/

bool more = true;

int time_left;
long timeout = m_timeout * 1000;
wxDateTime current_time = wxDateTime::UNow();
unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout;

while (more)
{
current_time = wxDateTime::UNow();
time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond());
if ((!timeout) || (time_left <= 0))
break;

ret = m_socket->Write((const char *)buffer, nbytes);

if (ret > 0)
{
total += ret;
nbytes -= ret;
buffer = (const char *)buffer + ret;
}

// If we got here and wxSOCKET_WAITALL is not set, we can leave
// now. Otherwise, wait until we send all the data or until there
// is an error.
//
more = nbytes > 0;
}
}

return total;
}
Attachments
socket.cpp
(36.25 KiB) Downloaded 51 times

tsanikgr
In need of some credit
In need of some credit
Posts: 1
Joined: Thu May 10, 2012 9:16 am

Re: wxTCP... and recursive Yield

Post by tsanikgr » Thu May 10, 2012 9:27 am

Thank you for this guys.

So is feelthat's solution (socket.cpp file)
or lowjoel's solution (wxApp::Yield)

the proper on to use?

Thank you in advance!
Nikos

Post Reply