Multithreaded Server in c++ : Memory leakage - c++

I am writing a multithreaded server in c++(linux). My problem is that my code runs fine for initial few requests but after that it shows "free:Invalid pointer". I know this error can come from any part of my code but for the below snippet I want to know suggestions if I am going on right track.
// This is helper function used in pthread_create
void *Parse::serveRequest_helper(void *c)
{
Parse *P1 =(Parse *)c;
P1->serveRequest();
}
// On this function 10 threads are continously working
void Parse::serveRequest()
{
pthread_detach(pthread_self());
while(1)
{
pthread_mutex_lock(&print_lock);
if(requestqueue.empty())
pthread_cond_wait(&print_cond, &print_lock);
SendData *S = new SendData;
clientInfo c;
cout<<"Inside Serving thread"<<endl;
c = requestqueue.front(); //assuming this queue has data coming from some other scheduler thread function
requestqueue.pop();
S->requestPrint(c);
delete S;
pthread_mutex_unlock(&print_lock);
cout<<" Inside Thread is out"<<endl;
}
}
// Below function I am using to write data of the file to socket.
// When a thread will handle this function, the file pointer will be local to the thread or for all 10 threads it will be global .. ?
void SendData::requestPrint(clientInfo c)
{
if (write(c.accept,"Requested File Data :", 21) == -1)
perror("send");
ifstream file;
file.open(c.filename.c_str());
if (file.is_open())
{
string read;
while (!file.eof() )
{
getline(file,read);
if (write(c.accept, read.c_str(), (size_t)read.size()) == -1)
perror("send");
}
}
file.close();
close(c.accept);
}

Related

Can't read anything using QSerialPort

I have created a wrapper library around QSerialPort. I want to communicate with my device. First, I send list command to my device and it should return list of commands supported by that device. However, while debugging my code, i observed that list command is being send to the device and device returns the proper response to it (i debugged using serial traffic sniffer Linux tools). However, i am not getting any response from my device using QSerialPort (while serial traffic sniffer tool was disable). I am unable to get it work after testing it several times.
My Serial.h:
class Serial : public Print {
public:
Serial();
explicit Serial(const char *dev_path);
~Serial();
int begin(unsigned long baudrate);
int begin(unsigned long baudrate, uint8_t cfg);
void end(void);
int available(void) const;
bool availableForWrite(void) const;
void flush(void);
bool isError(void) const;
void reset(void);
unsigned long write(uint8_t c);
unsigned long write(uint8_t *p_data, unsigned long maxSize);
int read(void);
void close();
QSerialPort &getPort()
{
return *_p_port;
}
public slots:
void readyBe(void);
private:
QSerialPort *_p_port;
unsigned long _baudrate;
};
My Serial.cpp:
Serial::Serial()
{
_p_port = new QSerialPort();
if (_p_port == nullptr)
throw std::runtime_error("Can't allocate memory");
}
Serial::Serial(const char *dev_path)
{
_p_port = new QSerialPort(QString(dev_path), QApplication::instance());
if (_p_port == nullptr)
throw std::runtime_error("Can't allocate memory");
// _p_port->setPortName(QString(dev_path));
if (_p_port->open(QIODevice::ReadWrite) == false) {
throw std::runtime_error("Can't open the serial _p_port");
delete _p_port;
}
_p_port->setBaudRate(QSerialPort::Baud9600);
_p_port->setDataBits(QSerialPort::Data8);
_p_port->setParity(QSerialPort::NoParity);
_p_port->setStopBits(QSerialPort::OneStop);
_p_port->setFlowControl(QSerialPort::NoFlowControl);
}
Serial::~Serial()
{
if (_p_port != nullptr) {
end();
delete _p_port;
}
}
int Serial::begin(unsigned long baudrate)
{
if (_p_port->setBaudRate(baudrate, QSerialPort::AllDirections) == false)
return -1;
_baudrate = baudrate;
return 0;
}
void Serial::end()
{
if (_p_port->isOpen())
_p_port->close();
}
int Serial::available(void) const
{
int num_bytes = _p_port->bytesAvailable();
return num_bytes;
}
bool Serial::availableForWrite(void) const
{
if (_p_port->isWritable())
return true;
return false;
}
void Serial::flush()
{
_p_port->flush();
}
unsigned long Serial::write(uint8_t c)
{
if (_p_port->putChar(c))
return 1;
return 0;
}
unsigned long Serial::write(uint8_t *p_data, unsigned long maxSize)
{
return _p_port->write(reinterpret_cast<const char *>(p_data), (qint64)maxSize);
}
int Serial::read(void)
{
char c;
_p_port->getChar(&c);
return c;
}
void Serial::reset(void)
{
_p_port->clear(QSerialPort::AllDirections);
_p_port->clearError();
}
bool Serial::isError(void) const
{
if (_p_port->error() == QSerialPort::NoError)
return false;
return true;
}
And my main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// w.show();
Serial serial("ttyACM0");
if (serial.begin(115200))
std::cout << "Failed to set Baud rate" << std::endl;
std::cout << "Sending data" << std::endl;
// QObject::connect(&(serial.getPort()), SIGNAL(readyRead()), &serial, SLOT(readyBe()));
serial.print("list\r");
serial.flush();
while (true) {
while (true) {
while (serial.available() == 0) {
if (serial.isError()) {
std::cout << "Error" << std::endl;
// serial.reset();
}
}
char c = serial.read();
std::cout << c;
if (c == '\n')
break;
}
std::cout << std::endl;
}
return a.exec();
}
You've pretty much missed everything needed for this code to work: the event loop. I/O in real life is asynchronous. You can't just "read" from the port without having some means of getting informed when the data is available, and actually letting the asynchronous I/O requests get processed. Yes, there are some legacy APIs that let you do that, but they mostly lead to spaghetti code, wasted threads, and poor performance.
The while (serial.available() == 0) loop is a no-op. It does nothing to actually let the available() return any other value. All that available() does internally is read an integer member of a class. You never run any code that could update the value stored in that member. Even if you would convert this to serial.waitForReadyRead(), which does update the number of available bytes, you're still not spinning an event loop, and thus you won't be able to process timeouts, or react to any other events an application might need to react to. QIODevice::waitForReadyRead is only meant to do one thing: return when a readyRead signal would fire. It won't process any other events, and it's a crutch used to port blocking code and is not really meant for production use.
You should redesign your code to be asynchronous and driven by signals from QSerialPort. The work will then be done from within QCoreApplication::exec - you won't have a loop of your own. This inversion of control is critical for getting async I/O working.
See e.g. this answer for a very simple example of an async approach, and this answer for a more complete one.

socket: multithreading doesn't work when client reads messages

I have a server, which can accept two socket connections. It creates a thread for each socket so that messages can be sent parallel.
Now I'm trying to code my client.
I create a class named SocketThread as a thread of socket. Here is the main code:
void SocketThread::ReadData()
{
int n = 0;
while (!finished)
{
while ((n = read(sockfd, recvBuff, sizeof(Data))) > 0)
{
std::cout<<std::this_thread::get_id()<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
}
}
std::thread SocketThread::run()
{
return std::thread([=] { ReadData(); });
}
in the function main:
SocketThread s0("127.0.0.1", 10000);
SocketThread s1("127.0.0.1", 10000);
std::thread td0{sts[0].run()};
std::thread td1{sts[1].run()};
td0.join(); // stop here
td1.join();
// something else
When I execute the program, it will block at td0.join();, meaning that I can get the id of the thread td0 on the console and I can NEVER get the other thread.
However, when I remove (n = read(sockfd, recvBuff, sizeof(Data))) > 0, which means that now the client is just a simple thread, that it won't receive anything, things gonna be fine ---- I can get two ids of the two threads.
Why?
EDIT
It seems that I used join incorrectly.
What I need is that main doesn't execute //something else until the two threads get 1000 characters together.
What should I do?
You did not use join() incorrectly. If you want main() to block until both threads end, your code is correct : td0.join() will block until thread td0 ends, and the same for td1.
Now, if you want your threads to end after receiving sizeof(Data) bytes, your function void SocketThread::ReadData() should rather look like this :
void SocketThread::ReadData()
{
int n, total = 0;
while (!finished)
{
while ((n = read(sockfd, &recvBuff[total], sizeof(Data) - total)) > 0)
{
total += n;
}
if (n == -1)
{
// manage error here
}
if (n == 0)
{
std::cout << "client shut the socket down; got " << total << " bytes over " << sizeof(Data) << std::endl;
finished = true;
}
}
}
For a short explanation : there is no guarantee that you can get all data sent by client in a single read() operation, so you need to call read() and cumulate data into the buffer until you get a return value of 0 (meaning the client shut down the socket). read(sockfd, &recvBuff[total], sizeof(Data) - total) ensures that the incomming data is properly appended at the right position in the buffer.

How to achieve the concurrency of two threads? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I write a program to capture the packets using Library "Winpcap". ( How to complie WinPcap with VS2010? Please see this link: http://www.rhyous.com/2011/11/12/how-to-compile-winpcap-with-visual-studio-2010/)
I want to capture the packet(using pcap_loop()) and at the same time I process the packet in the same function void D. The code int x = 1; in function void D is only an easy example which represents some functions that can process the packet. The thread t calls void D. The thread tt calls the function startCap() which captures the packet.
I want to emphasize my question: I debug the program and it stops at the position of pcap_loop() in thread tt until pcap_loop() finishes. I set the parameter of pcap_loop() to make it to run without end because I need continious capture of packet. The result is that the program will not go to the next step int x = 1;. I want to run int x = 1; as thread tt runs. In a word, I wish that the both threads t and tt run at the same time. But the program runs only on thread tt without jumping out and run on thread t.
PS 1: int x = 1; keeps staying better in void D.
PS 2: There's no erros in compiling and debuging. But the program falls into the function pcap_loop which is in the thread tt.
Did I make my question clear?
The whole code:
Data.h
#ifndef DATA_H
#define DATA_H
#include <pcap/pcap.h>
#include <vector>
using namespace std;
struct PcapDevice
{
string name;
string description;
};
class Data
{
public:
Data();
~Data();
bool findDevices(vector<PcapDevice> &deviceList );
bool openDevices(const char * device);
void processPacket();
void startCap();
private:
pcap_t* inData;
char errbuf[256];
bool isCapturing;
pcap_if_t * m_pDevs;
};
#endif // DATA_H
Data.cpp
#include "Data.h"
#include <iostream>
// define pcap callback
void capture_callback_handler(unsigned char *userData, const struct pcap_pkthdr* pkthdr, const unsigned char * packet)
{
((Data*) userData)->processPacket();
}
Data::Data()
{
memset(errbuf,0,PCAP_ERRBUF_SIZE);
isCapturing = false;
inData = NULL;
m_pDevs = NULL;
}
Data::~Data()
{
}
// process the packet
void Data::processPacket()
{
return ;
}
// find local adapter
bool Data::findDevices(vector<PcapDevice> &deviceList )
{
m_pDevs = NULL;
int res = pcap_findalldevs(&m_pDevs, errbuf);
if(0 == res)
{
pcap_if_t * pIter = m_pDevs;
while(pIter != NULL)
{
PcapDevice device;
device.description = pIter->description;
device.name = pIter->name;
deviceList.push_back(device);
pIter = pIter->next;
}
return true;
}
else
{
printf("PCAP: no devices found\n");
}
return false;
}
// open the adapter
bool Data::openDevices(const char *device)
{
if ( (inData = pcap_open_live(device, 8192, 1, 512, errbuf)) == NULL)
{
return false;
}
return true;
}
// start the process of capturing the packet
void Data::startCap()
{
if ( inData == NULL ){
fprintf(stderr, "ERROR: no source set\n" );
return;
}
// free the list of device(adapter)
pcap_freealldevs(m_pDevs);
Data* data = this;
isCapturing = true;
// capture in the loop
if ( pcap_loop(inData, -1, capture_callback_handler, (unsigned char *) data) == -1)
{
fprintf(stderr, "ERROR: %s\n", pcap_geterr(inData) );
isCapturing = false;
}
}
main.cpp
#include <WinSock2.h>
#include <Windows.h>
#include <time.h>
#include "Data.h"
#include <boost\thread\thread.hpp>
#include <boost\function.hpp>
struct parameter
{
Data* pData;
};
void D(void* pParam)
{
// init the parameter
parameter* pUserParams = (parameter*)pParam;
boost::function<void()> f;
// the capture thread will be started
f = boost::bind(&Data::startCap, pUserParams->pData);
boost::thread tt(f);
tt.join();
// I want to work on the packet at the same time, the code "int x=1" is only an easy example
// and it represents a series of functions that can process the packet. I want to run those function as the thread tt runs.
int x = 1;
}
void main()
{
Data oData;
parameter pPara ;
pPara.pData = &oData;
std::vector<PcapDevice> DevList;
oData.findDevices(DevList);
int num = DevList.size()-1;
oData.openDevices(DevList[num].name.c_str());
boost::thread t(D,(void*)&pPara);
t.join();
}
Calling tt.join() will wait until the thread finishes (that is, startCap() returns) before executing the next statement.
You can simply put your int x = 1; before the join(); however, the thread may have not have even started at that point. If you want to ensure the thread is running, or up to a certain point before processing int x = 1; you can use a condition_variable:
The condition_variable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until:
a notification is received from another thread
void Data::startCap(std::condition_variable& cv)
{
if ( inData == NULL ){
fprintf(stderr, "ERROR: no source set\n" );
return;
}
// free the list of device(adapter)
pcap_freealldevs(m_pDevs);
Data* data = this;
isCapturing = true;
// Notify others that we are ready to begin capturing packets
cv.notify_one();
// capture in the loop
if ( pcap_loop(inData, -1, capture_callback_handler, (unsigned char *) data) == -1)
{
fprintf(stderr, "ERROR: %s\n", pcap_geterr(inData) );
isCapturing = false;
}
}
void D(void* pParam)
{
// init the parameter
parameter* pUserParams = (parameter*)pParam;
// Create conditional_variable
std::conditional_variable cv;
// Pass the conditional_variable by reference to the thread
boost::thread tt(&Data::startCap, pUserParams->pData, std::ref(cv));
// Wait until the thread notifies us it's ready:
cv.wait();
// Process packets etc.
int x = 1;
// Wait for the thread to finish
tt.join();
}
Now D() will start the thread tt and then wait until startCaps has reached a certain point (where it calls notify_one()) before we continuing doing things.

multiple buffers using threads

I need some algorithm help with a multithreaded program I'm writing. It's basically the cp command in unix, but with a read thread and a write thread. I'm using semaphores for thread synchronization. I have structs for buffer and thread data defined as
struct bufType {
char buf[BUFFER_SIZE];
int numBytes;
};
struct threadData {
int fd;
bufType buf;
};
and a global array of bufType. Code for my main is
int main(int argc, const char * argv[])
{
int in, out;
pthread_t Producer, Consumer;
threadData producerData, consumerData;
if (argc != 3)
{
cout << "Error: incorrect number of params" << endl;
exit(0);
}
if ((in = open(argv[1], O_RDONLY, 0666)) == -1)
{
cout << "Error: cannot open input file" << endl;
exit(0);
}
if ((out = open(argv[2], O_WRONLY | O_CREAT, 0666)) == -1)
{
cout << "Cannot create output file" << endl;
exit(0);
}
sem_init(&sem_empty, 0, NUM_BUFFERS);
sem_init(&sem_full, 0, 0);
pthread_create (&Producer, NULL, read_thread, (void *) &producerData);
pthread_create (&Consumer, NULL, write_thread, (void *) &consumerData);
pthread_join(Producer, NULL);
pthread_join(Consumer, NULL);
return 0;
}
and read and write threads:
void *read_thread(void *data)
{
threadData *thread_data;
thread_data = (threadData *) data;
while((thread_data->buf.numBytes = slow_read(thread_data->fd, thread_data->buf.buf, BUFFER_SIZE)) != 0)
{
sem_post(&sem_full);
sem_wait(&sem_empty);
}
pthread_exit(0);
}
void *write_thread(void *data)
{
threadData *thread_data;
thread_data = (threadData *) data;
sem_wait(&sem_full);
slow_write(thread_data->fd, thread_data->buf.buf, thread_data->buf.numBytes);
sem_post(&sem_empty);
pthread_exit(0);
}
So my issue is in what to assign to my threadData variables in main, and my semaphore logic in the read and write threads. I appreciate any help you're able to give
Being a windows guy who does not use file descriptors I might be wrong with the in's and out's but I think this needs to be done in your main in order to setup the threadData structures.
producerData.fd = in;
consumerData.fd = out;
Then declare ONE SINGLE object of type bufType for both structures. Change for example the definition of threadData to
struct threadData {
int fd;
bufType* buf;
};
and in your Main, you write
bufType buffer;
producerData.buf = &buffer;
consumerData.buf = &buffer;
Then both threads will use a common buffer. Otherwise you would be writing to the producerData buffer, but the consumerData buffer will stay empty (and this is where your writer thread is looking for data)
Then you need to change your signalling logic. Right now your program cannot accept input that exceeds BUFFER_SIZE, because your write thread will only write once. There needs to be a loop around it. And then you need some mechanism that signals the writer thread that no more data will be sent. For example you could do this
void *read_thread(void *data)
{
threadData *thread_data;
thread_data = (threadData *) data;
while((thread_data->buf->numBytes = slow_read(thread_data->fd, thread_data->buf->buf, BUFFER_SIZE)) > 0)
{
sem_post(&sem_full);
sem_wait(&sem_empty);
}
sem_post(&sem_full); // Note that thread_data->buf->numBytes <= 0 now
pthread_exit(0);
}
void *write_thread(void *data)
{
threadData *thread_data;
thread_data = (threadData *) data;
sem_wait(&sem_full);
while (thread_data->buf->numBytes > 0)
{
slow_write(thread_data->fd, thread_data->buf->buf, thread_data->buf->numBytes);
sem_post(&sem_empty);
sem_wait(&sem_full);
}
pthread_exit(0);
}
Hope there are no more errors, did not test solution. But the concept should be what you were asking for.
You could use a common buffer pool, either a circular array or a linked lists. Here is a link to a zip of a Windows example that is similar to what you're asking, using linked lists as part of a inter-thread messaging system to buffer data. Other than the creation of the mutexes, semaphores, and the write thread, the functions are small and simple. mtcopy.zip .

Do I need to close fds when reading and writing to the pipe among threads created using pthread_create?

There is a client server application I am working on. Below is the code from client side.
pipe_input, pipe_output are shared variables.
int fds[2];
if (pipe(fds)) {
printf("pipe creation failed");
} else {
pipe_input = fds[0];
pipe_output = fds[1];
reader_thread_created = true;
r = pthread_create(&reader_thread_id,0,reader_thread,this);
}
void* reader_thread(void *input)
{
unsigned char id;
int n;
while (1) {
n = read(pipe_input , &id, 1);
if (1 == n) {
//process
}if ((n < 0) ) {
printf("ERROR: read from pipe failed");
break;
}
}
printf("reader thread stop");
return 0;
}
There is a writer thread also which writes data on event change from server.
void notify_client_on_event_change(char id)
{
int n;
n= write(pipe_output, &id, 1);
printf("message written to pipe done ");
}
My question is do I need to close the write end in reader thread and read end in case of writer thread. In the destructor, I am waiting for reader thread to exit but sometimes it doesn't exit from reader thread.
[...] do i need to close the write end in reader thread and read end in case of writer thread[?]
As those fds "are shared", closing them in one thread would close them for all threads. That is not what you want, I suspect.