c++ linux send uninitialised sockets memory - c++

I'm new and I'm using debian 10 x64. Why is error in the line with SEND? Someone can sugest me how to fix that problem?
send(socket, (char*)m_MsgBuf+sendBytes, std::min(m_MsgSize-sendBytes+2, 1000),
I got that ERROR LOG:
==24819== Thread 3:
==24819== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==24819== at 0x51442B4: __libc_send (send.c:28)
==24819== by 0x51442B4: send (send.c:23)
==24819== by 0x1FCFC9: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:117)
==24819== by 0x231624: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==24819== by 0x22ECF4: Protocol76::sendThingAppear(Thing const*) (protocol76.cpp:3039)
==24819== by 0x214DE1: Player::onThingAppear(Thing const*) (player.cpp:2165)
==24819== by 0x1829D0: Game::sendAddThing(Player*, Position const&, Thing const*) (game.cpp:7005)
==24819== by 0x16789F: Game::placeCreature(Position&, Creature*, int*) (game.cpp:1260)
==24819== by 0x223995: Protocol76::ConnectPlayer(int*) (protocol76.cpp:66)
==24819== by 0x208C43: ConnectionHandler(void*) (otserv.cpp:575)
==24819== by 0x5139F26: start_thread (pthread_create.c:479)
==24819== by 0x55F12AE: clone (clone.S:95)
==24819== Address 0x111137f1 is 289 bytes inside a block of size 16,912 alloc'd
==24819== at 0x4836DEF: operator new(unsigned long) (vg_replace_malloc.c:344)
==24819== by 0x2086ED: ConnectionHandler(void*) (otserv.cpp:510)
==24819== by 0x5139F26: start_thread (pthread_create.c:479)
==24819== by 0x55F12AE: clone (clone.S:95)
==24819==
CODE:
bool NetworkMessage::WriteToSocket(SOCKET socket)
{
if (m_MsgSize == 0)
return true;
m_MsgBuf[0] = (unsigned char)(m_MsgSize);
m_MsgBuf[1] = (unsigned char)(m_MsgSize >> 8);
bool ret = true;
int32_t sendBytes = 0;
int32_t flags = 0;
int32_t retry = 0;
flags = MSG_DONTWAIT; // 2 ?
do
{
int32_t b = send(socket, (char*)m_MsgBuf+sendBytes, std::min(m_MsgSize-sendBytes+2, 1000), flags);
if(b <= 0)
{
int32_t errnum;
if(errnum == EWOULDBLOCK)
{
b = 0;
OTSYS_SLEEP(10);
retry++;
if(retry == 10)
{
ret = false;
break;
}
}
else
{
ret = false;
break;
}
}
sendBytes += b;
}while(sendBytes < m_MsgSize+2);
return ret;
}
==930== Thread 3:
==930== Conditional jump or move depends on uninitialised value(s)
==930== at 0x1FCFE7: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:106)
==930== by 0x208340: ConnectionHandler(void*) (otserv.cpp:427)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930== by 0x55F12AE: clone (clone.S:95)
==930==
==930== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==930== at 0x51442B4: __libc_send (send.c:28)
==930== by 0x51442B4: send (send.c:23)
==930== by 0x1FCFD9: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:100)
==930== by 0x231650: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==930== by 0x22ED20: Protocol76::sendThingAppear(Thing const*) (protocol76.cpp:3039)
==930== by 0x214E0D: Player::onThingAppear(Thing const*) (player.cpp:2165)
==930== by 0x1829D0: Game::sendAddThing(Player*, Position const&, Thing const*) (game.cpp:7005)
==930== by 0x16789F: Game::placeCreature(Position&, Creature*, int*) (game.cpp:1260)
==930== by 0x2239C1: Protocol76::ConnectPlayer(int*) (protocol76.cpp:66)
==930== by 0x208C6F: ConnectionHandler(void*) (otserv.cpp:575)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930== by 0x55F12AE: clone (clone.S:95)
==930== Address 0x111198d1 is 289 bytes inside a block of size 16,912 alloc'd
==930== at 0x4836DEF: operator new(unsigned long) (vg_replace_malloc.c:344)
==930== by 0x208719: ConnectionHandler(void*) (otserv.cpp:510)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930== by 0x55F12AE: clone (clone.S:95)
==930==
==930== Conditional jump or move depends on uninitialised value(s)
==930== at 0x1FCFE7: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:106)
==930== by 0x231650: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==930== by 0x22ED20: Protocol76::sendThingAppear(Thing const*) (protocol76.cpp:3039)
==930== by 0x214E0D: Player::onThingAppear(Thing const*) (player.cpp:2165)
==930== by 0x1829D0: Game::sendAddThing(Player*, Position const&, Thing const*) (game.cpp:7005)
==930== by 0x16789F: Game::placeCreature(Position&, Creature*, int*) (game.cpp:1260)
==930== by 0x2239C1: Protocol76::ConnectPlayer(int*) (protocol76.cpp:66)
==930== by 0x208C6F: ConnectionHandler(void*) (otserv.cpp:575)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930== by 0x55F12AE: clone (clone.S:95)
==930== Thread 2:
==930== Conditional jump or move depends on uninitialised value(s)
==930== at 0x1FCFE7: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:106)
==930== by 0x231650: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==930== by 0x214089: Player::flushMsg() (player.cpp:1867)
==930== by 0x182338: Game::flushSendBuffers() (game.cpp:6879)
==930== by 0x17AAB2: Game::checkCreature(unsigned int) (game.cpp:5461)
==930== by 0x1A4B67: std::mem_fun1_t<void, Game, unsigned int>::operator()(Game*, unsigned int) const (stl_function.h:1284)
==930== by 0x1A1668: std::binder2nd<std::mem_fun1_t<void, Game, unsigned int> >::operator()(Game* const&)const (binders.h:158)
==930== by 0x19BCCD: boost::detail::function::void_function_obj_invoker1<std::binder2nd<std::mem_fun1_t<void, Game, unsigned int>>,void, Game*>::invoke(boost::detail::function::function_buffer&, Game*) (function_template.hpp:159)
==930== by 0x23810D: boost::function1<void, Game*>::operator()(Game*) const (function_template.hpp:768)
==930== by 0x237FBC: TSchedulerTask::operator()(Game*) (scheduler.h:63)
==930== by 0x166D2B: Game::eventThread(void*) (game.cpp:1045)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930==
==930== Thread 3:
==930== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==930== at 0x51442B4: __libc_send (send.c:28)
==930== by 0x51442B4: send (send.c:23)
==930== by 0x1FCFD9: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:100)
==930== by 0x231650: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==930== by 0x214089: Player::flushMsg() (player.cpp:1867)
==930== by 0x182338: Game::flushSendBuffers() (game.cpp:6879)
==930== by 0x224573: Protocol76::parsePacket(NetworkMessage&) (protocol76.cpp:405)
==930== by 0x223A3F: Protocol76::ReceiveLoop() (protocol76.cpp:86)
==930== by 0x208E70: ConnectionHandler(void*) (otserv.cpp:611)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930== by 0x55F12AE: clone (clone.S:95)
==930== Address 0x11119f5f is 1,967 bytes inside a block of size 16,912 alloc'd
==930== at 0x4836DEF: operator new(unsigned long) (vg_replace_malloc.c:344)
==930== by 0x208719: ConnectionHandler(void*) (otserv.cpp:510)
==930== by 0x5139F26: start_thread (pthread_create.c:479)
==930== by 0x55F12AE: clone (clone.S:95)
==930==
I use code like this:
bool NetworkMessage::WriteToSocket(SOCKET socket)
{
if (m_MsgSize == 0)
return true;
m_MsgBuf[0] = (unsigned char)(m_MsgSize);
m_MsgBuf[1] = (unsigned char)(m_MsgSize >> 8);
bool ret = true;
int32_t sendBytes = 0;
int32_t flags = 0;
int32_t retry = 0;
flags = MSG_DONTWAIT; // 2 ?
while (sendBytes != m_MsgSize)
{ /* != rather than < */
int32_t b = send(socket, (char*)m_MsgBuf+sendBytes, std::min(m_MsgSize-sendBytes+2, 1000), flags);
if(b <= 0)
{
int32_t errnum;
if(errnum == EWOULDBLOCK)
{
b = 0;
OTSYS_SLEEP(10);
retry++;
if(retry == 10)
{
ret = false;
break;
}
}
else
{
ret = false;
break;
}
}
sendBytes += b;
}
return ret;
}
EDIT
the last time when i had similar error I needed to use that code and now everything is working: sigemptyset(&sigh.sa_mask); OR memset(&sigh, 0, sizeof(sigh)); here i found all msgBuf and msg Size in my project files. Do U see something intresting here? m_MsgBuf wklejto.pl/828244 m_MsgSize wklejto.pl/828245
EDIT
so I did this, in file NetworkMessage.cpp I have added under AddString/AddU32/AddU16/AddByte this:
#ifdef CHECKVAL
checkval(m_MsgBuf+m_ReadPos, stringlen);
#endif
on the top this file I have added:
#include "player.h"
#ifdef CHECKVAL
extern int checkval(unsigned char * buff, int len);
#endif
and to the end added this code to player.cpp
#ifdef CHECKVAL
int checkval(unsigned char * buff, int len)
{
int r = 0;
buff -= len;
while (len--)
r += *buff++;
return r;
}
#endif
and also I have changed char to unsigned char - bcs I got error invalid conversion from ‘unsigned char*’ to ‘char*’
to END I added to compilator this -DCHECKVAL
after that I see same error
==15290== Thread 3:
==15290== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==15290== at 0x51442B4: __libc_send (send.c:28)
==15290== by 0x51442B4: send (send.c:23)
==15290== by 0x1FCFDC: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:105)
==15290== by 0x231728: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==15290== by 0x22EDF8: Protocol76::sendThingAppear(Thing const*) (protocol76. cpp:3039)
==15290== by 0x214E99: Player::onThingAppear(Thing const*) (player.cpp:2165)
==15290== by 0x1829D0: Game::sendAddThing(Player*, Position const&, Thing const*) (game.cpp:7005)
==15290== by 0x16789F: Game::placeCreature(Position&, Creature*, int*) (game.cpp:1260)
==15290== by 0x223A99: Protocol76::ConnectPlayer(int*) (protocol76.cpp:66)
==15290== by 0x208CFB: ConnectionHandler(void*) (otserv.cpp:575)
==15290== by 0x5139F26: start_thread (pthread_create.c:479)
==15290== by 0x55F12AE: clone (clone.S:95)
==15290== Address 0x11116331 is 289 bytes inside a block of size 16,912 alloc'd
==15290== at 0x4836DEF: operator new(unsigned long) (vg_replace_malloc.c:344)
==15290== by 0x2087A5: ConnectionHandler(void*) (otserv.cpp:510)
==15290== by 0x5139F26: start_thread (pthread_create.c:479)
==15290== by 0x55F12AE: clone (clone.S:95)
==15290==
==15290== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==15290== at 0x51442B4: __libc_send (send.c:28)
==15290== by 0x51442B4: send (send.c:23)
==15290== by 0x1FCFDC: NetworkMessage::WriteToSocket(int) (networkmessage.cpp:105)
==15290== by 0x231728: Protocol76::flushOutputBuffer() (protocol76.cpp:3574)
==15290== by 0x214115: Player::flushMsg() (player.cpp:1867)
==15290== by 0x182338: Game::flushSendBuffers() (game.cpp:6879)
==15290== by 0x22464B: Protocol76::parsePacket(NetworkMessage&) (protocol76.cpp:405)
==15290== by 0x223B17: Protocol76::ReceiveLoop() (protocol76.cpp:86)
==15290== by 0x208EFC: ConnectionHandler(void*) (otserv.cpp:611)
==15290== by 0x5139F26: start_thread (pthread_create.c:479)
==15290== by 0x55F12AE: clone (clone.S:95)
==15290== Address 0x111169bf is 1,967 bytes inside a block of size 16,912 alloc'd
==15290== at 0x4836DEF: operator new(unsigned long) (vg_replace_malloc.c:344)
==15290== by 0x2087A5: ConnectionHandler(void*) (otserv.cpp:510)
==15290== by 0x5139F26: start_thread (pthread_create.c:479)
==15290== by 0x55F12AE: clone (clone.S:95)
==15290==
hmm.. but this function looks intresting ConnectionHandler in the line 510 is problem?
Protocol76* protocol;
protocol = new Protocol76(s);
and:
Protocol76::Protocol76(SOCKET s)
{
OTSYS_THREAD_LOCKVARINIT(bufferLock);
player = NULL;
pendingLogout = false;
windowTextID = 0;
readItem = NULL;
this->s = s;
}
full ConnectionHandler and password is 123
enter link description here
line 510 in the file is 152
how do u think?
something like this can be enough?
int checkval(unsigned char * buff, int len)
{
buff -= len;
ofstream bufile ("buff.txt");
if (bufile.is_open())
{
while (len--)
{
bufile << "buff: " << *buff << "len: " << len;
}
bufile.close();
}
}

Supposing you initialized m_MsgSize bytes in m_MsgBuf and you want to send them in a loop block by block whose size is
std::min(m_MsgSize-sendBytes+2, 1000)
because of the "+2" depending on the initial value of m_MsgSize you can send 1 or 2 extra bytes after the first m_MsgSize bytes, these extra bytes can be just non initialized or even out of m_MsgBuf with an undefined behavior
Notice also that if you do
int32_t sendBytes = 0
while (sendBytes != m_MsgSize) { /* != rather than < */
int32_t b = send(socket, (char*)m_MsgBuf+sendBytes, std::min(m_MsgSize-sendBytes+2, 1000), ...);
... error management
sendBytes += b;
}
because of the error introduced by the +2 you can have sendBytes greater than m_MsgSize with probable bad effects.
Just remove that "+2"
[edit after you edit you question/you answer]
Your +2 is not a problem in case m_MsgSize do not count the two additional bytes to send the length of the next bytes
valgrind signal few errors and they concern bytes inside the buffer, not the 1 or 2 last ones, for me that means you copy in m_MsgBuf few bytes non initialized. Sometimes valgrind does not signal immediately when a value was not initialized, for instance you can have :
int i; // not initialized
f(i); // nothing signaled by valgrind even i not initialized
...
void f(int i)
{
int j = i + 1; // here valgrind signal a non initialized value
I think you are in that case.
Note this may be a non error, imagine you do that :
// set some elements
char s[20];
...
strcpy(s, "aze");
...
memcpy(m_MsgBuf + 2, /* save 2 bytes for the length */
s, sizeof(s));
m_MsgSize = sizeof(s);
... may be some oher element added from m_MsgSize+2 and updating m_MsgSize
NetworkMessage::WriteToSocket(socket);
only 4 bytes was initialized in s but to have a constant size sent you send (at least) 20 bytes => 16 bytes in the buffer correspond to non initialized values => valgrind will signal them
To know if you are in a 'non error' case or if valgrind signals a real problem you have to analyze the setting of all the values you put in the buffer, but again warning valgrind can take time to signal the use of a non initialized value, that value may be was used by several intermediate location before to reach hte buffer you send
[edit from your remark giving piece of code]
The initialized value probably come from the caller of the methodes NetworkMessage::AddXXX, for instance NetworkMessage::AddByte receive in argument a non initialized byte.
The fact you have that class with dedicated method to add data in the buffer is a chance, you can modify their definitions with additional code to artificially use the bytes from the buffer to allow valgrind to detect a non initialized value. You can put the additional codes protected by #ifdef ... #endif to easily activate/deactivate it
For instance (use the type of m_MsgBuf to type the parameter buff of checkval, I used "char *" because I do not know the type of m_MsgBuf) :
#ifdef CHECKVAL
extern int checkval(char * buff, int len);
#endif
void NetworkMessage::AddByte(unsigned char value)
{
if(!canAdd(1))
return;
m_MsgBuf[m_ReadPos++] = value;
m_MsgSize++;
#ifdef CHECKVAL
checkval(m_MsgBuf+m_ReadPos, 1);
#endif
}
void NetworkMessage::AddU16(uint16_t value)
{
if(!canAdd(2))
return;
m_MsgBuf[m_ReadPos++] = (unsigned char)(value);
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 8);
m_MsgSize += 2;
#ifdef CHECKVAL
checkval(m_MsgBuf+m_ReadPos, 2);
#endif
}
void NetworkMessage::AddU32(uint32_t value)
{
if(!canAdd(4))
return;
m_MsgBuf[m_ReadPos++] = (unsigned char)(value);
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 8);
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 16);
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 24);
m_MsgSize += 4;
#ifdef CHECKVAL
checkval(m_MsgBuf+m_ReadPos, 4);
#endif
}
void NetworkMessage::AddString(const char* value)
{
uint32_t stringlen = (uint32_t) strlen(value);
if(!canAdd(stringlen+2) || stringlen > 8192)
return;
#ifdef USING_VISUAL_2005
strcpy_s((char*)m_MsgBuf + m_ReadPos, stringlen, value); //VISUAL
#else
AddU16((uint16_t)stringlen);
strcpy((char*)m_MsgBuf + m_ReadPos, value);
#endif //USING_VISUAL_2005
m_ReadPos += stringlen;
m_MsgSize += stringlen;
#ifdef CHECKVAL
checkval(m_MsgBuf+m_ReadPos, stringlen);
#endif
}
checkval have to access to each byte, for instance :
#ifdef CHECKVAL
int checkval(char * buff, int len)
{
int r = 0;
buff -= len;
while (len--)
r += *buff++;
return r;
}
#endif
and place checkval in an other file than where *NetworkMessage:Addxxx" are defined to be sure the compiler cannot detect it is useless to compute the sum of bytes from the buffer or useless to call checkval because the return value is never used and checkval has no side effect.
If to sum the byte is not enough to force valgrind to check if the bytes are initialized or not, change the definition for instance to save the bytes in a file etc
Of course compile defining CHECKVAL through compiler option, or just adding temporary
#define CHECKVAL
before the definition of checkval and before its declaration
When valgrind will detect a non initialized byte in checkval you will be able to know where the value come from looking at the stack of calls also produced by valgrind

Related

Runtime free error while deleting user space stack

I am trying to create a user space stack and run functions using this stack.
Following are the steps I am doing.
Allocate a space for the stack.
Before calling a function, switch the stack pointer to the new location.
Also try to store previous or original stack pointer
Return of the called function
Restore the original stack pointer
I implemented the following based on the above points:
/* Ubuntu 18.04 x86_64 */
/* Compiler gcc version 7.5.0 */
#include <iostream>
#include <cassert>
#include <memory>
class Thread {
public:
/* stack will point to lowest addr of th User Stack */
unsigned char * stack = nullptr;
/*stack_ptr will point to the Highest addr of the User Stack */
unsigned char* stack_ptr = nullptr;
int stack_size = 0;
Thread() {
stack_size = 16*64; // 1024 B
stack = new unsigned char[stack_size];
/*stack_ptr points to the highest memory of this space*/
stack_ptr = stack + stack_size;
}
~Thread() {
std::cout <<"User stack deleted"<< std::endl;
if(stack != nullptr)
delete[] stack;
}
void func(int x,int y) {
std::cout <<"Hello from the func ["<<x<<"] ["<<y<<"]"<< std::endl;
}
};
int main() {
/* createa a User level Thread */
Thread t;
/* Some random local variable */
// int a[100];
unsigned char* stk = t.stack_ptr;
/* Note: rsp = current stack top */
uint64_t prev_stack = 0; /* for assert checking */
uint64_t x = 7; /*some random value, just for stack alighment of 16B */
asm("movq %%rsp, %%r11\n\t" /* save current stack ptr to r11(or rax etc.) */
"movq %%r11, %[out1]\n\t" /* just for assert check later */
"movq %[in1], %%rsp\n\t" /* change rsp to stk, i.e. to our own stack top */
"pushq %%r11\n\t" /* Push r11 or prev stack ptr to current stack */
"pushq %[in2]\n\t" /* for stack alignment only */
:[out1] "=m" (prev_stack) /*just for assert check later */
:[in1] "m" (stk),[in2] "m" (x) /* two inputs */
:);
// call the func, this func
// will will use our own stack
t.func(1,2);
/*just for checking x */
uint64_t y;
uint64_t _prev_stack;
asm(
"popq %[out1]\n\t" /* y = stack.pop() */
"popq %%rsp\n\t" /* restore stack: rsp = stack.pop() */
"movq %%rsp, %[out2]\n\t" /* just for checking */
:[out1] "=m" (y),[out2] "=m" (_prev_stack) /* two outputs */
:
:
);
assert(prev_stack == _prev_stack && "Main's stack not restored!");
std::cout <<std::hex<<"Stack restored = "<< prev_stack << std::endl;
assert(x == y && "x and y are not equal!!");
std::cout <<"Program Ended!" << std::endl;
}
I have added couple of extra checks, just for debug purpose.
The following output is generated:
Hello from the func [1] [2]
Stack restored = 7ffd55eb8ea0
Program Ended!
User stack deleted
munmap_chunk(): invalid pointer
[1] 27337 abort (core dumped) ./a.out
It seems that, I can safely (?) return to the original function, because the instruction pointer is restored automatically (due to callq and retq operation sequence, gcc compiler did this) and the program also gets back the original rsp or the stack top. The rbp pointer is also taken care of by the compiler.
But I get an error in the destructor of the Thread class.
I tried to debug on my own using gdb, but I could not find any reason for observed the error:
Here are the output of the gdb backtrace
_GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
>>> bt
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00001555545f2801 in __GI_abort () at abort.c:79
#2 0x000015555463b897 in __libc_message (action=action#entry=do_abort, fmt=fmt#entry=0x155554768b9a "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3 0x000015555464290a in malloc_printerr (str=str#entry=0x15555476a7a8 "munmap_chunk(): invalid pointer") at malloc.c:5350
#4 0x0000155554649ecc in munmap_chunk (p=0x614e60) at malloc.c:2846
#5 __GI___libc_free (mem=0x614e70) at malloc.c:3117
#6 0x0000000000400e2d in Thread::~Thread() ()
#7 0x0000000000400bdc in main ()
However valgrind shows no leaks.
==27982== HEAP SUMMARY:
==27982== in use at exit: 0 bytes in 0 blocks
==27982== total heap usage: 3 allocs, 3 frees, 74,752 bytes allocated
==27982==
==27982== All heap blocks were freed -- no leaks are possible
(Although valgrind warns : Warning: client switching stacks?, I think it is normal w.r.t to the above code)
Observation: If I comment out the if(stack != nullptr) delete[] stack line, error goes out
but valgrind shows the following:
=28019== 1,024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28019== at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28019== by 0x108ED7: Thread::Thread() (test.cpp:20)
==28019== by 0x108BBD: main (test.cpp:36)
I am really confused with the memory free error and no leak status. What could be the cause of such memory deallocation error ? Am I doing any mistake while saving and restoring old and new stacks ?
Thanks.
Update
I simplified the code:
/* Ubuntu 18.04 x86_64 */
/* Compiler gcc version 7.5.0 */
#include <iostream>
#include <cassert>
#include <memory>
const int _stack_size = 16*64; // 1024B
void func(int x,int y) {
std::cout <<"Hello from the func ["<<x<<"] ["<<y<<"]"<< std::endl;
}
int main() {
unsigned char * stackBase = new unsigned char[_stack_size];
unsigned char * stackTop = stackBase + _stack_size;
std::cout <<"Before "<<std::hex <<(void*)(stackBase) << std::endl;
asm volatile("movq %%rsp, %%r11\n\t" /* save current stack ptr to r11(or rax etc.) */
"movq %[in1], %%r12\n\t"
"movq %%r12, %%rsp\n\t" /* change rsp to stk, i.e. to our own stack top */
"pushq %%r11\n\t" /* Push r11 or prev stack ptr to current stack */
// "pushq %%rbp\n\t"
: /*no input */
:[in1] "m" (stackTop) /* two inputs */
:"r11","r12","rsp");
func(1,2);
asm volatile(
"popq %%rsp\n\t" /* restore stack: rsp = stack.pop() */
:/* no outputs */
:/* no inputs */
:"rsp");
std::cout <<"Program Ended!" << std::endl;
std::cout <<"After "<<std::hex<<(void*)(stackBase) << std::endl;
delete[] stackBase;
}
But it still shows the double free error:
Before 0x555e80926e70
Hello from the func [1] [2]
Program Ended!
After 0x555e80926e70
double free or corruption (out)
[1] 4343 abort (core dumped) ./a.out
Error in runtine with -fsanitize=address option:
Before 0x619000000080
ASAN:DEADLYSIGNAL
=================================================================
==5605==ERROR: AddressSanitizer: stack-overflow on address 0x618ffffffb90 (pc 0x14b656131576 bp 0x619000000418 sp 0x618ffffffb98 T0)
#0 0x14b656131575 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x51575)
#1 0x14b655e39039 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (/usr/local/gcc-10/lib64/libstdc++.so.6+0x12c039)
#2 0x564202743e4b in func(int, int) (/home/deka/Academic/userLevelThread/a.out+0x2e4b)
#3 0x5642027445ca in main (/home/deka/Academic/userLevelThread/a.out+0x35ca)
#4 0x14b654c1cb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#5 0x564202743d49 in _start (/home/deka/Academic/userLevelThread/a.out+0x2d49)
SUMMARY: AddressSanitizer: stack-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x51575)
==5605==ABORTING

Segmentation fault with malloc "unlink"

I am getting a segmentation fault that is internal to malloc. Here is the trace of the error via gdb (Note: everything frome frame 4 and above is my code).
#0 0xf7d109dd in _int_malloc (av=av#entry=0xf7e45420 <main_arena>, bytes=bytes#entry=100)
at malloc.c:3697
#1 0xf7d12358 in __GI___libc_malloc (bytes=100) at malloc.c:2888
#2 0xf7efb4a5 in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#3 0xf7efb5ab in operator new[](unsigned int) () from /usr/lib/libstdc++.so.6
#4 0x0804f295 in GetDataFromMem (fileAddr=1744, size=-1) at ../userprog/exception.cc:709
#5 0x0804ec9d in ExecSC (bufAddr=1744, ptrAddr=2912) at ../userprog/exception.cc:578
#6 0x0804dde9 in ExceptionHandler (which=SyscallException) at ../userprog/exception.cc:191
#7 0x08051585 in Machine::RaiseException (this=0x805b8c8, which=SyscallException, badVAddr=0)
at ../machine/machine.cc:109
#8 0x08052ee3 in Machine::OneInstruction (this=0x805b8c8, instr=0x80628e8) at ../machine/mipssim.cc:535
#9 0x080519d0 in Machine::Run (this=0x805b8c8) at ../machine/mipssim.cc:40
#10 0x0804e74f in ForkBootStrap (val=0) at ../userprog/exception.cc:462
#11 0x08054338 in ThreadRoot ()
#12 0x00000000 in ?? ()
The line in my code that resulted in the fault:
int vpn = fileAddr / PageSize;
int offset = fileAddr % PageSize;
int counter = 0;
bool nullhit = false;
char *buf;
if (size == -1)
{
int curSize = DEF_BUF_LEN; //100
buf = new char[curSize]; //SEGFAULT
The exact line where the segmentation fault occurred (within malloc code):
3687 else
3688 {
3689 size = chunksize (victim);
3690
3691 /* We know the first chunk in this bin is big enough to use. */
(gdb)
3692 assert ((unsigned long) (size) >= (unsigned long) (nb));
3693
3694 remainder_size = size - nb;
3695
3696 /* unlink */
3697 unlink (victim, bck, fwd); //SEGFAULTS HERE
3698
3699 /* Exhaust */
3700 if (remainder_size < MINSIZE)
3701 {
(gdb)
3702 set_inuse_bit_at_offset (victim, size);
3703 if (av != &main_arena)
3704 victim->size |= NON_MAIN_ARENA;
3705 }
3706
3707 /* Split */
3708 else
3709 {
3710 remainder = chunk_at_offset (victim, nb);
3711
(gdb)
3712 /* We cannot assume the unsorted list is empty and therefore
3713 have to perform a complete insert here. */
3714 bck = unsorted_chunks (av);
3715 fwd = bck->fd;
3716 if (__builtin_expect (fwd->bk != bck, 0))
3717 {
3718 errstr = "malloc(): corrupted unsorted chunks 2";
3719 goto errout;
3720 }
3721 remainder->bk = bck;
The values of victim, bck, and fwd in unlink are respectively :
(gdb) p victim
$6 = (mchunkptr) 0x805c650
(gdb) p bck
$7 = (mchunkptr) 0xffffffff
(gdb) p fwd
$8 = (mchunkptr) 0xf7e454e8 <main_arena+200>
I am not really sure what the causes for this are. Any insight is appreciated.

Interruption in a linux multithreaded app generate SIGSEGV

I have a x86_64 multithreaded application where I try to emulate avr interrupts: when interrupt occurs application and all threads are suspended while interrupt handler execute defined actions.
I thought signals were the solution to do this so I'm trying to catch SIGUSR1 signal, but when I raise SIGUSR1 program exit with a segmentation fault error before executing apply function. (I have tried mutex in isr and signals but removed as actually they run in the main thread)
The code is within 5 files.
isr.h
#ifndef __ISR_H__
#define __ISR_H__
typedef void (*routine_t)(void);
class InterruptServiceRoutine
{
routine_t routine;
bool locked = true;
public:
InterruptServiceRoutine(routine_t isr);
void apply();
void unlock(){locked = false;};
};
typedef InterruptServiceRoutine ISR_t;
#endif // __ISR_H__
isr.cpp:
#include <ISR.h>
InterruptServiceRoutine::InterruptServiceRoutine(routine_t isr): routine(isr){}
void InterruptServiceRoutine::apply()
{
if (!locked) routine();
}
Signals.h:
#ifndef __SIGNALS_H__
#define __SIGNALS_H__
#include <vector>
#include <ISR.h>
#include <signal.h>
class Logger;
class Signals
{
private:
Logger& log;
std::vector<ISR_t*> isr_table;
public:
Signals(Logger&);
~Signals();
unsigned int count(void);
void clear(void);
void connect(ISR_t &isr);
void apply(int);
};
#endif // __SIGNALS_H__
Signals.cpp:
#include <signal.h>
#include <pthread.h>
#include <functional>
#include <ISR.h>
#include <Signals.h>
#include <Logger.h>
using namespace std;
void Signals::apply(int)
{
sigset_t sigs_to_block;
sigfillset(&sigs_to_block);
pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
unsigned int num_interrupts = count();
for (unsigned int i=0; i < num_interrupts; ++i)
{
isr_table[i]->apply();
}
pthread_sigmask(SIG_SETMASK, NULL, NULL);
}
Signals::Signals(Logger& _log): log(_log)
{
clear();
auto _apply = bind1st(mem_fun(&Signals::apply), this);
struct sigaction new_action;
new_action.sa_handler = (__sighandler_t) &_apply;
new_action.sa_flags = 0;
sigfillset(&new_action.sa_mask);
sigaction(SIGUSR1, &new_action, NULL);
pthread_sigmask(SIG_SETMASK, NULL, NULL);
}
Signals::~Signals() {
struct sigaction new_action;
new_action.sa_handler = SIG_DFL;
new_action.sa_flags = 0;
sigemptyset(&new_action.sa_mask);
sigaddset(&new_action.sa_mask, SIGUSR1);
sigaction(SIGUSR1, &new_action, NULL);
clear();
}
void Signals::clear(void)
{
isr_table.clear();
isr_table.reserve(20);
}
unsigned int Signals::count(void)
{
return isr_table.size();
}
void Signals::connect(ISR_t &isr)
{
isr_table.push_back(&isr);
}
SignalsTest.test:
#include <signal.h>
#include <pthread.h>
#include <cxxtest/TestSuite.h>
#include <ISR.h>
#include <Signals.h>
#include <Logger.h>
volatile sig_atomic_t isr_called_count;
void isr(void)
{
++isr_called_count;
}
class SignalsTestSuite: public CxxTest::TestSuite
{
Logger log;
Signals handler;
public:
SignalsTestSuite(void): handler(log){}
void setUp()
{
handler.clear();
isr_called_count = 0;
}
/* ... truncated for more visibility ... */
void testWhenRaiseSIGUSRItCallsAvailableRoutine(void)
{
ISR_t routine(&isr);
routine.unlock();
handler.connect(routine);
handler.connect(routine);
raise(SIGUSR1);
TS_ASSERT_EQUALS(isr_called_count, 2);
}
};
Debug informations:
GNU gdb (Gentoo 7.7.1 p1) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./out/signals...done.
(gdb) r
Starting program: test/out/signals
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Running 3 tests..
Program received signal SIGUSR1, User defined signal 1.
0x00007ffff7bd0beb in raise (sig=10) at ../sysdeps/unix/sysv/linux/pt-raise.c:36
36 return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid),
(gdb) bt
#0 0x00007ffff7bd0beb in raise (sig=10) at ../sysdeps/unix/sysv/linux/pt-raise.c:36
#1 0x0000000000403f38 in SignalsTestSuite::testWhenRaiseSIGUSRItCallsAvailableRoutine (this=this#entry=0x631cc0 <suite_SignalsTestSuite>)
at test/SignalsTest.test:62
#2 0x0000000000403f92 in TestDescription_suite_SignalsTestSuite_testWhenRaiseSIGUSRItCallsAvailableRoutine::runTest (this=<optimized out>) at out/signals.cpp:38
#3 0x000000000040424e in CxxTest::RealTestDescription::run (this=<optimized out>) at /opt/cxxtest/cxxtest/RealDescriptions.cpp:109
#4 0x0000000000409afb in CxxTest::TestRunner::runTest (this=this#entry=0x7fffffffd29f, td=...) at /opt/cxxtest/cxxtest/TestRunner.h:85
#5 0x0000000000409c76 in CxxTest::TestRunner::runSuite (this=this#entry=0x7fffffffd29f, sd=...) at /opt/cxxtest/cxxtest/TestRunner.h:72
#6 0x0000000000409e15 in CxxTest::TestRunner::runWorld (this=this#entry=0x7fffffffd29f) at /opt/cxxtest/cxxtest/TestRunner.h:57
#7 0x0000000000409f52 in CxxTest::TestRunner::runAllTests (listener=...) at /opt/cxxtest/cxxtest/TestRunner.h:34
#8 0x0000000000409f93 in CxxTest::ErrorFormatter::run (this=this#entry=0x7fffffffd320) at /opt/cxxtest/cxxtest/ErrorFormatter.h:59
#9 0x000000000040aa89 in CxxTest::Main<CxxTest::ErrorPrinter> (tmp=..., argc=argc#entry=1, argv=argv#entry=0x7fffffffd448) at /opt/cxxtest/cxxtest/TestMain.h:109
#10 0x0000000000407f62 in main (argc=1, argv=0x7fffffffd448) at out/runner.cpp:18
(gdb) l
31 that. */
32 pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
33 if (__glibc_unlikely (pid < 0))
34 pid = -pid;
35
36 return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid),
37 sig);
38 }
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffd210 in ?? ()
(gdb) bt
#0 0x00007fffffffd210 in ?? ()
#1 <signal handler called>
#2 0x00007ffff7bd0beb in raise (sig=10) at ../sysdeps/unix/sysv/linux/pt-raise.c:36
#3 0x0000000000403f38 in SignalsTestSuite::testWhenRaiseSIGUSRItCallsAvailableRoutine (this=this#entry=0x631cc0 <suite_SignalsTestSuite>)
at test/SignalsTest.test:62
#4 0x0000000000403f92 in TestDescription_suite_SignalsTestSuite_testWhenRaiseSIGUSRItCallsAvailableRoutine::runTest (this=<optimized out>) at out/signals.cpp:38
#5 0x000000000040424e in CxxTest::RealTestDescription::run (this=<optimized out>) at /opt/cxxtest/cxxtest/RealDescriptions.cpp:109
#6 0x0000000000409afb in CxxTest::TestRunner::runTest (this=this#entry=0x7fffffffd29f, td=...) at /opt/cxxtest/cxxtest/TestRunner.h:85
#7 0x0000000000409c76 in CxxTest::TestRunner::runSuite (this=this#entry=0x7fffffffd29f, sd=...) at /opt/cxxtest/cxxtest/TestRunner.h:72
#8 0x0000000000409e15 in CxxTest::TestRunner::runWorld (this=this#entry=0x7fffffffd29f) at /opt/cxxtest/cxxtest/TestRunner.h:57
#9 0x0000000000409f52 in CxxTest::TestRunner::runAllTests (listener=...) at /opt/cxxtest/cxxtest/TestRunner.h:34
#10 0x0000000000409f93 in CxxTest::ErrorFormatter::run (this=this#entry=0x7fffffffd320) at /opt/cxxtest/cxxtest/ErrorFormatter.h:59
#11 0x000000000040aa89 in CxxTest::Main<CxxTest::ErrorPrinter> (tmp=..., argc=argc#entry=1, argv=argv#entry=0x7fffffffd448) at /opt/cxxtest/cxxtest/TestMain.h:109
#12 0x0000000000407f62 in main (argc=1, argv=0x7fffffffd448) at out/runner.cpp:18
(gdb) l
Line number 39 out of range; ../sysdeps/unix/sysv/linux/pt-raise.c has 38 lines.
(gdb) s
Cannot find bounds of current function
(gdb) c
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
Memory informations:
$ valgrind --leak-check=full --show-leak-kinds=all ./out/signals
==31715== Memcheck, a memory error detector
==31715== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==31715== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==31715== Command: ./out/signals
==31715==
Running 3 tests..==31715==
==31715== Process terminating with default action of signal 11 (SIGSEGV)
==31715== Bad permissions for mapped region at address 0xFFEFFF1F0
==31715== at 0xFFEFFF1F0: ???
==31715== by 0x409F92FF: ???
==31715== by 0xFFF: ???
==31715== by 0x40AA88FF: ???
==31715==
==31715== HEAP SUMMARY:
==31715== in use at exit: 176 bytes in 2 blocks
==31715== total heap usage: 2 allocs, 0 frees, 176 bytes allocated
==31715==
==31715== 16 bytes in 1 blocks are still reachable in loss record 1 of 2
==31715== at 0x4C294C0: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==31715== by 0x408AB1: CxxTest::ErrorPrinter::ErrorPrinter(std::ostream&, char const*, char const*) (ErrorPrinter.h:43)
==31715== by 0x407F4C: main (runner.cpp:17)
==31715==
==31715== 160 bytes in 1 blocks are still reachable in loss record 2 of 2
==31715== at 0x4C294C0: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==31715== by 0x40B2E3: __gnu_cxx::new_allocator<InterruptServiceRoutine*>::allocate(unsigned long, void const*) (new_allocator.h:104)
==31715== by 0x40B315: std::_Vector_base<InterruptServiceRoutine*, std::allocator<InterruptServiceRoutine*> >::_M_allocate(unsigned long) (in test/out/signals)
==31715== by 0x40B941: InterruptServiceRoutine** std::vector<InterruptServiceRoutine*, std::allocator<InterruptServiceRoutine*> >::_M_allocate_and_copy<std::move_iterator<InterruptServiceRoutine**> >(unsigned long, std::move_iterator<InterruptServiceRoutine**>, std::move_iterator<InterruptServiceRoutine**>) (stl_vector.h:1138)
==31715== by 0x40BA28: std::vector<InterruptServiceRoutine*, std::allocator<InterruptServiceRoutine*> >::reserve(unsigned long) (vector.tcc:75)
==31715== by 0x40AE7D: Signals::clear() (Signals.cpp:57)
==31715== by 0x40AF50: Signals::Signals(Logger&) (Signals.cpp:32)
==31715== by 0x403531: SignalsTestSuite::SignalsTestSuite() (in test/out/signals)
==31715== by 0x40302D: __static_initialization_and_destruction_0(int, int) (signals.cpp:18)
==31715== by 0x403144: _GLOBAL__sub_I_suite_SignalsTestSuite_init (signals.cpp:39)
==31715== by 0x4147EC: __libc_csu_init (elf-init.c:88)
==31715== by 0x5A8DA34: (below main) (libc-start.c:245)
==31715==
==31715== LEAK SUMMARY:
==31715== definitely lost: 0 bytes in 0 blocks
==31715== indirectly lost: 0 bytes in 0 blocks
==31715== possibly lost: 0 bytes in 0 blocks
==31715== still reachable: 176 bytes in 2 blocks
==31715== suppressed: 0 bytes in 0 blocks
==31715==
==31715== For counts of detected and suppressed errors, rerun with: -v
==31715== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Erreur de segmentation
I've tried to figure out why there are missing symbols (0x00007fffffffd210 in ?? () and at 0xFFEFFF1F0: ??? ...):
(gdb) info share
From To Syms Read Shared Object Library
0x00007ffff7ddca80 0x00007ffff7df5960 Yes /lib64/ld-linux-x86-64.so.2
No linux-vdso.so.1
0x00007ffff7bc6a40 0x00007ffff7bd2781 Yes /lib64/libpthread.so.0
0x00007ffff79bb360 0x00007ffff79be0dc Yes /lib64/librt.so.1
0x00007ffff770f5f0 0x00007ffff77733c3 Yes /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/libstdc++.so.6
0x00007ffff73c04f0 0x00007ffff7425266 Yes /lib64/libm.so.6
0x00007ffff71a7ac0 0x00007ffff71b6e45 Yes /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/libgcc_s.so.1
0x00007ffff6e2c430 0x00007ffff6f53b44 Yes /lib64/libc.so.6
But can't find a way to get "linux-vdso.so.1" on gentoo.
I'm a beginner in C++ what I'm doing wrong with memory ?
Have you a tip to fix this ?
Edit1:
routine_t and __sighandler_t types are aliases for: void (*)(void)
I believe that you can safely ignore the error. A StackOverflow member with a reputation in the top 0.25% of members (!) says that this warning "Could not load shared library symbols for linux-vdso.so.1." is something you can safely ignore. To see the post, go here:
Could not load shared library symbols for linux-vdso.so.1. while debugging
Problem solved thanks to Igor Tandetnik.
Finally the following code function.
signals.h:
#ifndef __SIGNALS_H__
#define __SIGNALS_H__
#include <vector>
#include <ISR.h>
#include <signal.h>
using namespace std;
class Logger;
class Signals
{
private:
Logger& log;
static bool action_handled;
void reserve();
public:
static void start();
static void stop();
static std::vector<ISR_t*> isr_table;
Signals(Logger& _log);
~Signals();
unsigned int count(void);
void clear(void);
void connect(ISR_t&);
static void apply(int);
static void unmask_pthread_signals();
static void mask_pthread_signals();
};
#endif // __SIGNALS_H__
signals.cpp:
#include <functional>
#include <signal.h>
#include <pthread.h>
#include <ISR.h>
#include <Signals.h>
#include <Logger.h>
using namespace std;
vector<ISR_t*> Signals::isr_table={};
bool Signals::action_handled=false;
void Signals::apply(int)
{
mask_pthread_signals();
for (unsigned int i=0; i < isr_table.size(); ++i)
{
isr_table[i]->apply();
}
unmask_pthread_signals();
}
Signals::Signals(Logger& _log): log(_log){
clear();
start();
}
Signals::~Signals() {
clear();
stop();
}
void Signals::clear(void)
{
isr_table.clear();
isr_table.reserve(0);
}
unsigned int Signals::count(void)
{
return isr_table.size();
}
void Signals::start()
{
if (action_handled) return;
struct sigaction new_action;
new_action.sa_handler = (__sighandler_t) &Signals::apply;
new_action.sa_flags = 0;
sigemptyset(&new_action.sa_mask);
sigaction(SIGUSR1, &new_action, NULL);
unmask_pthread_signals();
action_handled = true;
}
void Signals::stop()
{
if (!action_handled) return;
struct sigaction new_action;
new_action.sa_handler = SIG_DFL;
sigemptyset(&new_action.sa_mask);
sigaction(SIGUSR1, &new_action, NULL);
mask_pthread_signals();
action_handled = false;
}
void Signals::unmask_pthread_signals()
{
sigset_t signals_mask;
sigemptyset(&signals_mask);
pthread_sigmask(SIG_SETMASK, &signals_mask, NULL);
}
void Signals::mask_pthread_signals()
{
sigset_t signals_mask;
sigfillset(&signals_mask);
pthread_sigmask(SIG_SETMASK, &signals_mask, NULL);
}
void Signals::reserve()
{
if (isr_table.capacity() <= isr_table.size()) {
isr_table.reserve(isr_table.capacity() + 20);
}
}
void Signals::connect(ISR_t &isr)
{
start();
reserve();
isr_table.push_back(&isr);
}

cant figure out segmentation fault using boost threads

I'm developing a stomp client in c++ using boost library for sockets and threads.
The program consists of two major classes SocketListener which gets frame from the socket and UserInterface which receives commands from the user and sends frames to the server.
I can't figure out a segmentation fault i get when i shutdown the SocketListener. (when i call the shutdown method)
Using valgrind i get this error:
==8450== Thread 2:
==8450== Invalid read of size 8
==8450== at 0x588AF8B: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
==8450== by 0x417846: SocketListener::shutdown(std::string) (SocketListener.cpp:114)
==8450== by 0x41D2A7: userInterface::shutdown() (UserInterface.cpp:123)
==8450== by 0x41C7ED: userInterface::run() (UserInterface.cpp:37)
==8450== by 0x415F0B: boost::_mfi::mf0<void, userInterface>::operator()(userInterface*) const (mem_fn_template.hpp:49)
==8450== by 0x415DF1: void boost::_bi::list1<boost::_bi::value<userInterface*> >::operator()<boost::_mfi::mf0<void, userInterface>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, userInterface>&, boost::_bi::list0&, int) (bind.hpp:253)
==8450== by 0x415B4E: boost::_bi::bind_t<void, boost::_mfi::mf0<void, userInterface>, boost::_bi::list1<boost::_bi::value<userInterface*> > >::operator()() (bind_template.hpp:20)
==8450== by 0x4157E7: boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, userInterface>, boost::_bi::list1<boost::_bi::value<userInterface*> > > >::run() (thread.hpp:74)
==8450== by 0x5046C2C: thread_proxy (in /usr/local/boost/1.51.0/lib/libboost_thread.so.1.51.0)
==8450== by 0x5260E99: start_thread (pthread_create.c:308)
==8450== by 0x5DF53FC: clone (clone.S:112)
==8450== Address 0x50 is not stack'd, malloc'd or (recently) free'd
==8450==
==8450==
==8450== Process terminating with default action of signal 11 (SIGSEGV)
==8450== Access not within mapped region at address 0x50
==8450== at 0x588AF8B: std::string::assign(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16)
==8450== by 0x417846: SocketListener::shutdown(std::string) (SocketListener.cpp:114)
==8450== by 0x41D2A7: userInterface::shutdown() (UserInterface.cpp:123)
==8450== by 0x41C7ED: userInterface::run() (UserInterface.cpp:37)
==8450== by 0x415F0B: boost::_mfi::mf0<void, userInterface>::operator()(userInterface*) const (mem_fn_template.hpp:49)
==8450== by 0x415DF1: void boost::_bi::list1<boost::_bi::value<userInterface*> >::operator()<boost::_mfi::mf0<void, userInterface>, boost::_bi::list0>(boost::_bi::type<void>, boost::_mfi::mf0<void, userInterface>&, boost::_bi::list0&, int) (bind.hpp:253)
==8450== by 0x415B4E: boost::_bi::bind_t<void, boost::_mfi::mf0<void, userInterface>, boost::_bi::list1<boost::_bi::value<userInterface*> > >::operator()() (bind_template.hpp:20)
==8450== by 0x4157E7: boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, userInterface>, boost::_bi::list1<boost::_bi::value<userInterface*> > > >::run() (thread.hpp:74)
==8450== by 0x5046C2C: thread_proxy (in /usr/local/boost/1.51.0/lib/libboost_thread.so.1.51.0)
==8450== by 0x5260E99: start_thread (pthread_create.c:308)
==8450== by 0x5DF53FC: clone (clone.S:112)
==8450== If you believe this happened as a result of a stack
==8450== overflow in your program's main thread (unlikely but
==8450== possible), you can try to increase the size of the
==8450== main thread stack using the --main-stacksize= flag.
==8450== The main thread stack size used in this run was 8388608.
here is the code:
main.cpp:
main() {
StompClient* client = new StompClient();
userInterface* ui = new userInterface(client); // this doesnt invoke the segfault but SocketListener::shutdown() is called from this object
SocketListener* socketListener = new SocketListener(client,ui);
boost::thread* uiThread = new boost::thread(&userInterface::run, ui);
boost::thread* socketThread= new boost::thread(&SocketListener::run, socketListener);
socketThread->join();
uiThread->join();
}
SocketListener.h:
class SocketListener {
public:
SocketListener(StompClient* client, userInterface* ui);
virtual ~SocketListener();
void run();
void exportHtml();
void processMessage(StompFrame* frame);
void shutdown(string* fileName);
private:
StompClient* _client;
bool _shutdown;
userInterface* _UI;
string _userName;
};
SocketLisener.cpp:
void SocketListener::run() {
StompParser parser;
StompFrame* frame = 0;
while (!_shutdown) {
if (frame != 0) {
delete frame;
}
frame = _client->getFrame();
if (frame == 0) {
continue;
}
//switch on all the messages cases. the problem happens regardless of message type, even when not receiving anything.
}
void SocketListener::exportHtml() {
//writing to file using poco logger
}
void SocketListener::shutdown(string* fileName) {
cout << "shutting down socket listener" <<endl;
_userName = *fileName; // this is line 114 which valgrind points to
_shutdown = true;
cout << "shutting down socket listener2" <<endl; // this line never gets printed
}

Implements timeout using boost::asio::async_read without call run on io_service

I'm trying to read from a input source (in this case stdin) with a timeout. Due to the design of the existing application where this have to fit is it not possible to call run on my io_service.
Here is my try so far:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
void set_result( boost::optional<boost::system::error_code> * a, boost::system::error_code b ) {
if( b == 0)
a->reset( b );
}
void receive(boost::asio::io_service & io, boost::asio::posix::stream_descriptor & stream, boost::asio::streambuf & result){
boost::optional<boost::system::error_code> timer_result;
boost::optional<boost::system::error_code> read_result;
boost::asio::deadline_timer timer( io );
timer.expires_from_now( boost::posix_time::milliseconds(5000) );
timer.async_wait( boost::bind(&set_result, &timer_result, _1) );
boost::asio::async_read(
stream,
result,
boost::asio::transfer_at_least(1),
boost::bind( &set_result, &read_result, _1 ));
boost::system::error_code ec;
while(1) {
io.reset();
io.poll_one(ec);
if ( read_result ) {
timer.cancel();
return;
} else if ( timer_result )
throw std::runtime_error("timeout");
}
}
void receive(boost::asio::io_service & io, boost::asio::posix::stream_descriptor & stream, size_t size, boost::asio::streambuf & result){
while( result.size() < size )
receive(io, stream, result);
}
int main(int argc, const char *argv[])
{
boost::asio::io_service io;
boost::asio::posix::stream_descriptor in(io, ::dup(STDIN_FILENO));
for(int i = 0; i < 5; i++){
std::cout << i << " Type in 4 chareters and press enter" << std::endl << std::endl;
std::cout << "in> ";
std::cout.flush();
try {
boost::asio::streambuf buf;
receive(io, in, 5, buf);
std::cout << "out> ";
std::copy(boost::asio::buffer_cast<const char *>(buf.data()), boost::asio::buffer_cast<const char *>(buf.data()) + buf.size(), std::ostream_iterator<char>(std::cout));
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
}
}
return 0;
}
At my first look, I thought that it was working, but after playing more around with the test app, I got some segmentations faults.
I found that something bad happens if I wait for the first query to timeout, and then enter 5 chars the next.
Here is what valgrind says:
==17216== Memcheck, a memory error detector
==17216== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==17216== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==17216== Command: ./ccTalkScan
==17216==
0 Type in 4 chareters and press enter
asdf
0 system:0
1 Type in 4 chareters and press enter
0 system:125
0 system:0
==17216== Invalid read of size 8
==17216== at 0x546EB4A: ??? (setcontext.S:60)
==17216== by 0x425245: receive(boost::asio::io_service&, boost::asio::posix::basic_stream_descriptor<boost::asio::posix::stream_descriptor_service>&, unsigned long, boost::asio::basic_streambuf<std::allocator<char> >&) (ccTalkScan.cxx:321)
==17216== by 0x42535E: main (ccTalkScan.cxx:333)
==17216== Address 0x7feffdfa8 is not stack'd, malloc'd or (recently) free'd
==17216==
==17216== Invalid read of size 8
==17216== at 0x546EB52: ??? (setcontext.S:63)
==17216== by 0x425245: receive(boost::asio::io_service&, boost::asio::posix::basic_stream_descriptor<boost::asio::posix::stream_descriptor_service>&, unsigned long, boost::asio::basic_streambuf<std::allocator<char> >&) (ccTalkScan.cxx:321)
==17216== by 0x42535E: main (ccTalkScan.cxx:333)
==17216== Address 0x7feffdf98 is not stack'd, malloc'd or (recently) free'd
==17216==
==17216== Invalid read of size 8
==17216== at 0x546EB59: ??? (setcontext.S:64)
==17216== by 0x425245: receive(boost::asio::io_service&, boost::asio::posix::basic_stream_descriptor<boost::asio::posix::stream_descriptor_service>&, unsigned long, boost::asio::basic_streambuf<std::allocator<char> >&) (ccTalkScan.cxx:321)
==17216== by 0x42535E: main (ccTalkScan.cxx:333)
==17216== Address 0x7feffdf68 is not stack'd, malloc'd or (recently) free'd
==17216==
==17216== Invalid read of size 8
==17216== at 0x546EB4A: ??? (setcontext.S:60)
==17216== by 0x5E4BD2C: (below main) (in /lib64/libc-2.12.2.so)
==17216== Address 0x7feffe018 is not stack'd, malloc'd or (recently) free'd
==17216==
==17216== Invalid read of size 8
==17216== at 0x546EB52: ??? (setcontext.S:63)
==17216== by 0x5E4BD2C: (below main) (in /lib64/libc-2.12.2.so)
==17216== Address 0x7feffe008 is not stack'd, malloc'd or (recently) free'd
==17216==
==17216== Invalid read of size 8
==17216== at 0x546EB59: ??? (setcontext.S:64)
==17216== by 0x5E4BD2C: (below main) (in /lib64/libc-2.12.2.so)
==17216== Address 0x7feffdfd8 is not stack'd, malloc'd or (recently) free'd
==17216==
timeout
2 Type in 4 chareters and press enter
0 system:0
timeout
3 Type in 4 chareters and press enter
asdf
==17216== Syscall param readv(vector[...]) points to unaddressable byte(s)
==17216== at 0x5EF7A81: readv (in /lib64/libc-2.12.2.so)
==17216== by 0x42A77A: boost::asio::detail::descriptor_ops::non_blocking_read(int, iovec*, unsigned long, boost::system::error_code&, unsigned long&) (descriptor_ops.ipp:153)
==17216== by 0x4355D1: boost::asio::detail::descriptor_read_op_base<boost::asio::mutable_buffers_1>::do_perform(boost::asio::detail::reactor_op*) (descriptor_read_op.hpp:55)
==17216== by 0x4275DA: boost::asio::detail::reactor_op::perform() (reactor_op.hpp:40)
==17216== by 0x4288F9: boost::asio::detail::epoll_reactor::run(bool, boost::asio::detail::op_queue<boost::asio::detail::task_io_service_operation>&) (epoll_reactor.ipp:286)
==17216== by 0x429577: boost::asio::detail::task_io_service::do_one(boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>&, boost::asio::detail::task_io_service::idle_thread_info*) (task_io_service.ipp:264)
==17216== by 0x429165: boost::asio::detail::task_io_service::poll_one(boost::system::error_code&) (task_io_service.ipp:188)
==17216== by 0x4299B8: boost::asio::io_service::poll_one(boost::system::error_code&) (io_service.ipp:103)
==17216== by 0x424FDF: receive(boost::asio::io_service&, boost::asio::posix::basic_stream_descriptor<boost::asio::posix::stream_descriptor_service>&, boost::asio::basic_streambuf<std::allocator<char> >&) (ccTalkScan.cxx:308)
==17216== by 0x425245: receive(boost::asio::io_service&, boost::asio::posix::basic_stream_descriptor<boost::asio::posix::stream_descriptor_service>&, unsigned long, boost::asio::basic_streambuf<std::allocator<char> >&) (ccTalkScan.cxx:321)
==17216== by 0x42535E: main (ccTalkScan.cxx:333)
==17216== Address 0x65ba920 is 0 bytes inside a block of size 512 free'd
==17216== at 0x4C25C4F: operator delete(void*) (vg_replace_malloc.c:387)
==17216== by 0x432317: __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) (new_allocator.h:95)
==17216== by 0x430D67: std::_Vector_base<char, std::allocator<char> >::_M_deallocate(char*, unsigned long) (stl_vector.h:146)
==17216== by 0x42F4A0: std::_Vector_base<char, std::allocator<char> >::~_Vector_base() (stl_vector.h:132)
==17216== by 0x42CF5E: std::vector<char, std::allocator<char> >::~vector() (stl_vector.h:313)
==17216== by 0x42AEB5: boost::asio::basic_streambuf<std::allocator<char> >::~basic_streambuf() (basic_streambuf.hpp:114)
==17216== by 0x425374: main (ccTalkScan.cxx:333)
==17216==
0 system:0
4 Type in 4 chareters and press enter
0 system:125
0 system:0
timeout
==17216==
==17216== HEAP SUMMARY:
==17216== in use at exit: 168 bytes in 3 blocks
==17216== total heap usage: 63 allocs, 60 frees, 22,070 bytes allocated
I have tried different things to fix it, but I think that I might have misunderstood a thing or two here. So some help would be nice, and an example would be most appreciated ;)
The problem in the above implementation is that the async_reads which times out is never canceled. Here is how to do this:
while(1) {
io.reset();
io.poll_one(ec);
if ( read_result ) {
timer.cancel(); // cancel the timeout operation as it has not completed yet
return;
} else if ( timer_result ) {
stream.cancel(); // cancel the read operation as it has not completed yet
throw std::runtime_error("timeout");
}
}