I am doing serial IO on linux in c++ using multi-threading. Currently I am using a blocking read. That leaves me with no way stop the thread cought in the blocking read() except to forcefully terminate or interrupt the thread or use something like pthread cancellation. Now all over the net i see people scream at people suggesting they need to terminate there threads from a blocking IO. Usually its concerning memory leaks. Is there some magic memory leak that can appear out of a thread interruption as long as you clean up properly?
try
{
while(true)
{
blocking_read(fd,buffer,512);
}
}catch(interrupt_exception)
{
}
//clean up, close fd, release heap memory, usual stuff
Or is my only alternative something like the below or implement a higher level protocol ensuring the blocking read receives a sign off input enabling it to shut itself down.
try
{
while(running)
{
nonblocking_read(fd,buffer,512);
if(cancel)
running = false; //break return etc
}
}
//clean up, close fd, release heap memory, usual stuff
So again, do there happen some magic memory leak in read() if you interrupt the thread causing it to throw a exception.
Or should i simply not care and let the destructor kill the thread(i assume thread terminates when you delete your object holding the thread)? and do clean up there? like
class MyClass{
int fd;
Thread* myThread;
~MyClass(){
delete myThread;
close(fd);
}
};
Thanks for any help!
read()should not leak memory. With both blocking and nonblocking reads, the application code is still responsible for the management of the memory provided as thebufargument. Interruptingread()via a signal will not throw an exception, so if use signals, you will need to check the result and errno.read()is interrupted by a signal before reading data, -1 will be returned with errno set toEINTR.read()is interrupted by a signal after reading some data, POSIX allows for either -1 to be returned with errno set toEINTR, or forread()to return the number of bytes already read.If you use
pthread_cancel()then an exception will be thrown. With this approach, you have the following options:pthread_cleanup_push().pthread_setspecific().auto_ptr/unique_ptr.abi::__forced_unwindexception, perform cleanup, and rethrow.In general, consider avoiding thread cancellation. When possible, it is better, and more manageable, to have a shared flag that is used to break out of the loop. This allows the thread to perform any necessary cleanup, and prevents your implementation from being dependent on your threading library’s implementation and any of its quirks.
For your case, where you are using a blocking read, consider polling the fd to see if data is available via
select()with a timeout, and only callread()if the fd has data. This allows you to periodically check if the thread flag is set to no longer run, and prevents you from needing to deal with signals to interrupt the thread fromread(), asread()should no longer block waiting on data.Also, the behavior that occurs when deleting a thread object is dependent on the thread library. For example, deleting a
pthread_torboost::threadhas no effect on the associated thread’s execution.