wxSockets memory leacks

93 views
Skip to first unread message

Rossano Paris

unread,
Aug 20, 2013, 11:05:22 AM8/20/13
to wx-u...@googlegroups.com
Hi at all !
 
I'm using wxSockets features in a client/server application which should be able to Exchange data over the network using TCP protocol.
 
Such data exchanging could be very fast, nearly hundreds of small packages each second are sent from server to client and viceversa in a infinite loop.
The application should stay active 24 hours every day.
 
I noticed that there is a problem related to memory leaks.
Infact observing the two client/server processes using System monitor on a Linux system the amount of memory for both processes increases continuosly.
I've noticed this behaviour with the wxWidgets version 2.9.4 and it still is present in the new one version 2.9.5
 
I was able to reproduce such behaviour using the small source code of socket sample supplyed with wxWidgets package.
Attached at this message there is the source code I've modified to reproduce the problem.
To observe the behavior it is necessary:
- run both applications (they are built in static mode)
- connect the client to the server using the appropriate option.
- run the "TEST 1" option inside the TCP menu
Such test sends 5000 times a small package of data to the server and waits its answer.
using "System monitor" it will be easy to observe for both processes the anomaly behaviour related to their memory amount used.
 
Environment details:
wxWidgets version 2.9.5
SO: UBUNTU 12.04 LTS
IDE: CodeBlocks 12.11
Compiler: GCC 4.6
 
 
 
wxSocketsTest.zip

Igor Korot

unread,
Aug 22, 2013, 2:02:03 AM8/22/13
to wx-u...@googlegroups.com
Hi,
Could you please make a small patch to the sample instead of sending the .zip?
Thank you.


--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.
 
To unsubscribe, send email to wx-users+u...@googlegroups.com
or visit http://groups.google.com/group/wx-users

Rossano Paris

unread,
Aug 23, 2013, 10:37:06 AM8/23/13
to wx-u...@googlegroups.com
Hi, Igor and thank you for your answer.

Unfortunatelly I haven't got a patch, but I'm trying to investigate if what I've observed could be a bug or not.
Simply I've wanted to use the example delivered with wxWidgets library to understand whether even with such code was present the same and strange behaviour I've observed in my application or not.

Up to now, I'm able only to confirm that also using the example above mentioned the behaviour which look like a memory leack problem is present.
I've modified just a bit the original example's source code in order to introduce a loop into the first test. (Client side)
 
I'm not sure that the behavior I've observed is a bug, because i think that sockets features in wxWidgets library was already present for long.
And it seems surprising that noone stumbled over such kind of problem before now.
 
Many thanks for your time.
Feel free to ask me for other details if you need.
 
*************************
CLIENT SIDE CODE
*************************
void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
{
 int count = 5000;
 // Disable socket menu entries (exception: Close Session)
 m_busy = true;
 UpdateStatusBar();
 do {
  DoTest1();
  count--;
 } while (count > 0);
 m_busy = false;
 UpdateStatusBar();
}
void MyFrame::DoTest1()
{
 m_text->AppendText(_("\n=== Test 1 begins ===\n"));
 // Tell the server which test we are running
 unsigned char c = 0xBE;
 m_sock->Write(&c, 1);
 // Send some data and read it back. We know the size of the
 // buffer, so we can specify the exact number of bytes to be
 // sent or received and use the wxSOCKET_WAITALL flag. Also,
 // we have disabled menu entries which could interfere with
 // the test, so we can safely avoid the wxSOCKET_BLOCK flag.
 //
 // First we send a byte with the length of the string, then
 // we send the string itself (do NOT try to send any integral
 // value larger than a byte "as is" across the network, or
 // you might be in trouble! Ever heard about big and little
 // endian computers?)
 m_sock->SetFlags(wxSOCKET_WAITALL);
 const char *buf1 = "Test string (less than 256 chars!)";
 unsigned char len  = (unsigned char)(wxStrlen(buf1) + 1);
 wxCharBuffer buf2(wxStrlen(buf1));
 m_text->AppendText(_("Sending a test buffer to the server ..."));
 m_sock->Write(&len, 1);
 m_sock->Write(buf1, len);
 m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
 m_text->AppendText(_("Receiving the buffer back from server ..."));
 m_sock->Read(buf2.data(), len);
 m_text->AppendText(m_sock->Error() ? _("failed !\n") : _("done\n"));
 m_text->AppendText(_("Comparing the two buffers ..."));
 if (memcmp(buf1, buf2, len) != 0) {
  m_text->AppendText(_("failed!\n"));
  m_text->AppendText(_("Test 1 failed !\n"));
 }
 else {
  m_text->AppendText(_("done\n"));
  m_text->AppendText(_("Test 1 passed !\n"));
 }
 m_text->AppendText(_("=== Test 1 ends ===\n"));
}
 
*************************
SERVER SIDE CODE
*************************
void MyFrame::Test1(wxSocketBase *sock)
{
  TestLogger logtest("Test 1");
  // Receive data from socket and send it back. We will first
  // get a byte with the buffer size, so we can specify the
  // exact size and use the wxSOCKET_WAITALL flag. Also, we
  // disabled input events so we won't have unwanted reentrance.
  // This way we can avoid the infamous wxSOCKET_BLOCK flag.
  sock->SetFlags(wxSOCKET_WAITALL);
  // Read the size
  unsigned char len;
  sock->Read(&len, 1);
  wxCharBuffer buf(len);
  // Read the data
  sock->Read(buf.data(), len);
  wxLogMessage("Got the data, sending it back");
  // Write it back
  sock->Write(buf, len);
}
client.cpp
server.cpp

Vadim Zeitlin

unread,
Aug 23, 2013, 11:52:14 AM8/23/13
to wx-u...@googlegroups.com
On Fri, 23 Aug 2013 07:37:06 -0700 (PDT) Rossano Paris wrote:

RP> Simply I've wanted to use the example delivered with wxWidgets library to
RP> understand whether even with such code was present the same and strange
RP> behaviour I've observed in my application or not.

This is absolutely the right thing to do.

RP> Up to now, I'm able only to confirm that also using the example above
RP> mentioned the behaviour which look like a memory leack problem is present.
RP> I've modified just a bit the original example's source code in order to
RP> introduce a loop into the first test. (Client side)

If there is a leak, it should be reported by any memory leak detection
software even if the test is executed only once. Have you tried running the
sample under Valgrind? It probably reports plenty of errors (you typically
need to suppress quite a few reports about the system and GTK libraries)
but what you could do would be to run the sample once and just exit it
without doing anything and then run it under Valgrind again but this time
run the test and look at the difference in the output. If Valgrind reports
more memory leaks for the second run, it would be indeed an indication of a
memory leak in wxSocket code. And it could also point us to what exactly is
being leaked as Valgrind shows where was the memory allocated from.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Rossano Paris

unread,
Aug 26, 2013, 9:12:59 AM8/26/13
to wx-u...@googlegroups.com
Hi Vadim, thank you for your interest in this post.
I won't be able to test the example using Valgrind till the first week of September.

Meanwhile would you be so kind to post your impression after observing the picture  attached at this post ?
I've attached once again also the two example's files with the small modification I've done, if they could be helpfull.

Before diving into wxSocket code I'd like to be sure that what I'm observing really look like a memory leack problem.
I'm 99% sure, but it sounds so strange for a library so well implemented and tested.

Thank you very much ! 
Keep in touch !
client.cpp
image.jpg
server.cpp

Vadim Zeitlin

unread,
Aug 26, 2013, 6:47:24 PM8/26/13
to wx-u...@googlegroups.com
On Mon, 26 Aug 2013 06:12:59 -0700 (PDT) Rossano Paris wrote:

RP> Meanwhile would you be so kind to post your impression after observing the
RP> picture attached at this post ?

It does look like a memory leak. The increase in VM size is probably not
important but the "memory" column increase is very suspicious.

RP> Before diving into wxSocket code I'd like to be sure that what I'm
RP> observing really look like a memory leack problem.
RP> I'm 99% sure, but it sounds so strange for a library so well implemented
RP> and tested.

Unfortunately wxSocket hardly belongs in the "well implemented"
category. wxWidgets focus is mostly on the portable GUI development and my
recommendation since a long time was to use something else (e.g. ASIO) for
any non-trivial network applications. Of course, we still should memory
leaks in wxSocket, even so...

Rossano Paris

unread,
Sep 21, 2013, 6:45:17 AM9/21/13
to wx-u...@googlegroups.com
Hi Vadim.
I've run wxSocket example using valgrind to detect memory leaks.
Below I report what I've found.
I think, if I'm able to understand valgrind output, the memory leak depends on the two functions in wxSocketBase class called Read() and Write()
Below I've highlighted in red colour such functions.
 
Could you tell me if I well interpreted valgrind analisys ?
In case what I've oserved is correct, how could I report this result as a bug in wxWidgets ?

(1)
==4430== 70 (64 direct, 6 indirect) bytes in 1 blocks are definitely lost in loss record 2,520 of 3,449
==4430==    at 0x402BD74: malloc (vg_replace_malloc.c:270)
==4430==    by 0x47589AA: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
==4430==    by 0x828FE61: wxSocketFDBasedManager::Install_Callback(wxSocketImpl*, wxSocketNotify) (socketiohandler.cpp:63)
==4430==    by 0x82902FC: wxSocketImplUnix::DoEnableEvents(int, bool) (sockunix.cpp:109)
==4430==    by 0x82907AB: wxSocketImplUnix::EnableEvents(int) (sockunix.h:81)
==4430==    by 0x8290705: wxSocketImplUnix::ReenableEvents(int) (sockunix.h:54)
==4430==    by 0x828F996: wxSocketReadGuard::~wxSocketReadGuard() (socket.cpp:222)
==4430==    by 0x828C6A3: wxSocketBase::Read(void*, unsigned int) (socket.cpp:957)
==4430==    by 0x8060674: MyFrame::Test1(wxSocketBase*) (server.cpp:334)
==4430==    by 0x806172B: MyFrame::OnSocketEvent(wxSocketEvent&) (server.cpp:471)
==4430==    by 0x81DC986: wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const (appbase.cpp:601)
==4430==    by 0x81DC9E2: wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const (appbase.cpp:613)
 
(2)
==4430== 70 (64 direct, 6 indirect) bytes in 1 blocks are definitely lost in loss record 2,521 of 3,449
==4430==    at 0x402BD74: malloc (vg_replace_malloc.c:270)
==4430==    by 0x47589AA: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
==4430==    by 0x828FE61: wxSocketFDBasedManager::Install_Callback(wxSocketImpl*, wxSocketNotify) (socketiohandler.cpp:63)
==4430==    by 0x82902FC: wxSocketImplUnix::DoEnableEvents(int, bool) (sockunix.cpp:109)
==4430==    by 0x82907AB: wxSocketImplUnix::EnableEvents(int) (sockunix.h:81)
==4430==    by 0x8290705: wxSocketImplUnix::ReenableEvents(int) (sockunix.h:54)
==4430==    by 0x828F996: wxSocketReadGuard::~wxSocketReadGuard() (socket.cpp:222)
==4430==    by 0x828C6A3: wxSocketBase::Read(void*, unsigned int) (socket.cpp:957)
==4430==    by 0x80606AF: MyFrame::Test1(wxSocketBase*) (server.cpp:338)
==4430==    by 0x806172B: MyFrame::OnSocketEvent(wxSocketEvent&) (server.cpp:471)
==4430==    by 0x81DC986: wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const (appbase.cpp:601)
==4430==    by 0x81DC9E2: wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const (appbase.cpp:613)
 
(3)
==4430== 70 (64 direct, 6 indirect) bytes in 1 blocks are definitely lost in loss record 2,522 of 3,449
==4430==    at 0x402BD74: malloc (vg_replace_malloc.c:270)
==4430==    by 0x47589AA: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
==4430==    by 0x828FE61: wxSocketFDBasedManager::Install_Callback(wxSocketImpl*, wxSocketNotify) (socketiohandler.cpp:63)
==4430==    by 0x8290327: wxSocketImplUnix::DoEnableEvents(int, bool) (sockunix.cpp:111)
==4430==    by 0x82907AB: wxSocketImplUnix::EnableEvents(int) (sockunix.h:81)
==4430==    by 0x8290705: wxSocketImplUnix::ReenableEvents(int) (sockunix.h:54)
==4430==    by 0x828FA60: wxSocketWriteGuard::~wxSocketWriteGuard() (socket.cpp:248)
==4430==    by 0x828CD71: wxSocketBase::Write(void const*, unsigned int) (socket.cpp:1143)
==4430==    by 0x806077E: MyFrame::Test1(wxSocketBase*) (server.cpp:342)
==4430==    by 0x806172B: MyFrame::OnSocketEvent(wxSocketEvent&) (server.cpp:471)
==4430==    by 0x81DC986: wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const (appbase.cpp:601)
==4430==    by 0x81DC9E2: wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const (appbase.cpp:613)
==4430==
 
TEST 1
(1) wxSocketBase::Read(void*, unsigned int) (socket.cpp:957)  Called by  MyFrame::Test1(wxSocketBase*) (server.cpp:334)
(2) wxSocketBase::Read(void*, unsigned int) (socket.cpp:957)  Called by MyFrame::Test1(wxSocketBase*) (server.cpp:338)
(3) wxSocketBase::Write(void const*, unsigned int) (socket.cpp:1143) Called by MyFrame::Test1(wxSocketBase*) (server.cpp:342)
 
(1)(2)
socket.cpp:950 wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
socket.cpp:951 {
socket.cpp:952    wxSocketReadGuard read(this);
socket.cpp:953
socket.cpp:954    m_lcount_read = DoRead(buffer, nbytes);
socket.cpp:955    m_lcount = m_lcount_read;
socket.cpp:956
socket.cpp:957    return *this;
socket.cpp:958 }
 
(3)
socket.cpp:1136 wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
socket.cpp:1137 {
socket.cpp:1138     wxSocketWriteGuard write(this);
socket.cpp:1139
socket.cpp:1140     m_lcount_write = DoWrite(buffer, nbytes);
socket.cpp:1141     m_lcount = m_lcount_write;
socket.cpp:1142
socket.cpp:1143     return *this;
socket.cpp:1144 }

Vadim Zeitlin

unread,
Sep 29, 2013, 11:43:05 AM9/29/13
to wx-u...@googlegroups.com
On Sat, 21 Sep 2013 03:45:17 -0700 (PDT) Rossano Paris wrote:

RP> I've run wxSocket example using valgrind to detect memory leaks.
RP> Below I report what I've found.
RP> I think, if I'm able to understand valgrind output, the memory leak depends
RP> on the two functions in wxSocketBase class called Read() and Write()
...
RP> (1)
RP> ==4430== 70 (64 direct, 6 indirect) bytes in 1 blocks are definitely lost
RP> in loss record 2,520 of 3,449
RP> ==4430== at 0x402BD74: malloc (vg_replace_malloc.c:270)
RP> ==4430== by 0x47589AA: ??? (in
RP> /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
RP> ==4430== by 0x828FE61:
RP> wxSocketFDBasedManager::Install_Callback(wxSocketImpl*, wxSocketNotify)
RP> (socketiohandler.cpp:63)
RP> ==4430== by 0x82902FC: wxSocketImplUnix::DoEnableEvents(int, bool)
RP> (sockunix.cpp:109)
RP> ==4430== by 0x82907AB: wxSocketImplUnix::EnableEvents(int)
RP> (sockunix.h:81)
RP> ==4430== by 0x8290705: wxSocketImplUnix::ReenableEvents(int)
RP> (sockunix.h:54)
RP> ==4430== by 0x828F996: wxSocketReadGuard::~wxSocketReadGuard()
RP> (socket.cpp:222)
RP> ==4430== by 0x828C6A3: wxSocketBase::Read(void*, unsigned int)
RP> (socket.cpp:957)
RP> ==4430== by 0x8060674: MyFrame::Test1(wxSocketBase*) (server.cpp:334)
RP> ==4430== by 0x806172B: MyFrame::OnSocketEvent(wxSocketEvent&)
RP> (server.cpp:471)
RP> ==4430== by 0x81DC986: wxAppConsoleBase::HandleEvent(wxEvtHandler*, void
RP> (wxEvtHandler::*)(wxEvent&), wxEvent&) const (appbase.cpp:601)
RP> ==4430== by 0x81DC9E2: wxAppConsoleBase::CallEventHandler(wxEvtHandler*,
RP> wxEventFunctor&, wxEvent&) const (appbase.cpp:613)

Unfortunately I don't see any memory allocations in Install_Callback() at
all so I have no idea what is Valgrind trying to tell us here. My guess is
that the leak happens inside wxFDIOManager::AddInput() but I don't
understand why doesn't Valgrind show it to us then.

Perhaps somebody else has other ideas but I'm honestly stumped right now
and don't see how to debug this further.

Sorry,

Rossano Paris

unread,
Sep 30, 2013, 8:33:19 AM9/30/13
to wx-u...@googlegroups.com
Thank you for your time.

well ... I'm going to follow your first suggestion.
I'll take a look at ASIO library in order to use it instead of wxSockets classes

... but it's a pitty, expecially thinking at the incoming wxWidgets 3.0 version

regards
Rossano
Reply all
Reply to author
Forward
0 new messages