Segmentation fault when catching exceptions in a libpthread linked app ( linux, C++ ) - c++

I have this piece of code here:
These are functions used to create and stop a pthread:
void WatchdogController::conscious_process_handler_start() {
if ( debug ) cout << "WatchdogController: starting conscious process thread" << endl;
cn_pr_thread_active = true;
if ( pthread_create( &cn_pr_thread, NULL, conscious_process_handler, this ) < 0 ) {
cn_pr_thread_active = false;
throw WatchdogException( "Unable to start new thread" );
}
}
void WatchdogController::conscious_process_handler_stop() {
if ( debug ) cout << "WatchdogController: stopping conscious process thread" << endl;
cn_pr_thread_active = false;
int *retval;
pthread_join( cn_pr_thread, ( void ** )&retval );
if ( *retval < 0 ) {
delete retval;
string err = string( "Error returned by conscious_process_handler(): " ) + string( pthread_err );
throw WatchdogException( err.c_str() );
}
delete retval;
}
I use select() in function passed to pthread, and when stopped it returns an error resulting in return value from pthread being negative, but that's not the issue, I'll fix it later - problem is, that when the exception is thrown here:
throw WatchdogException( err.c_str() );
and caught here:
try {
watchdog_controller->hardware_watchdog_stop();
watchdog_controller->unconscious_process_handler_stop();
watchdog_controller->conscious_process_handler_stop();
}
catch ( HardwareWatchdogException &e ) {
cerr << "Error stopping hardware watchdog!" << endl;
cerr << e.get_reason() << endl;
string err = string( "Exception thrown by hardware watchdog controller" ) + string( e.get_reason() );
if ( log ) write_log( err.c_str() );
delete watchdog_controller;
return -1;
}
catch ( WatchdogException &e ) {
cerr << "Exception cought when exiting!" << endl;
cerr << e.get_reason() << endl;
string err = string( "Exception cought when exiting" ) + string( e.get_reason() );
if ( log ) write_log( err.c_str() );
delete watchdog_controller;
return -1;
}
I get segmentation fault then trying to access the object at this point:
cerr << e.get_reason() << endl;
What could be the reason?
Reference &e points to something, but it seems as if the address was invalid.
Here's the exception class:
class WatchdogException {
public:
/**
#brief Default constructor
*/
WatchdogException() : reason() {
}
/**
#brief Overloaded constructor - setting the error message
#param why Error message
*/
WatchdogException( const char *why ) : reason( why ) {
}
/**
#brief The destructor
*/
virtual ~WatchdogException() {
}
/**
#brief A getter for the error message
#return Returns a string containing error description
*/
virtual std::string get_reason() const {
return reason;
}
protected:
/**
#var reason String containing the error message
*/
std::string reason;
};

I am guessing that you are not properly allocating memory for retval, or that somehow you are returning an invalid pointer from cn_pr_thread, and that is why you get a segmentation fault when you call pthread_join.

In WatchDogException's constructor, are you remembering the pointer to the c-string passed in or are you making a copy of it.
If you're simply storing the pointer then when "err" goes out of scope when the exception is thrown the pointer returned by c_str() will be bad, hence your seg fault when you try and use it.

Related

Handling memory exhausted in Windows Qt app

My application can use a lot of memory and I want to be able to handle running out of memory gracefully. So I do this:
bool Application::notify( QObject* receiver, QEvent* event )
{
bool done = true;
try
{
done = QApplication::notify( receiver, event );
}
catch ( std::bad_alloc& ex )
{
releaseMemory();
qWarning() << "bad_alloc exception: " << ex.what();
m_outOfMemoryDlg->exec();
exit( 1 );
}
catch ( const std::exception& ex )
{
releaseMemory();
qWarning() << "exception: " << ex.what();
criticalMessage( nullptr, QString( "%1 has to close due to an exception. Please contact support." ).arg( APP_NAME ) );
exit( 2 );
}
catch ( ... )
{
releaseMemory();
qWarning() << "exception";
criticalMessage( nullptr, QString( "%1 has to close. Please contact support." ).arg( APP_NAME ) );
exit( 3 );
}
return done;
}
Where m_outOfMemoryDlg is a QDialog with a helpful message I create and hide at startup. This all works fine on macOS. I get a std::bad_alloc exception, the QDialog appears and the program shuts gracefully. But on Windows the whole OS just locks. The screen is frozen and I have to power off and back on to make it responsive.
In my .pro file I added:
CONFIG += exceptions
win32 {
QMAKE_CXXFLAGS_EXCEPTIONS_ON = /EHa
QMAKE_CXXFLAGS_STL_ON = /EHa
}
I also added:
#ifdef Q_OS_WIN
#include <new.h>
LONG WINAPI
exceptionFilter( struct _EXCEPTION_POINTERS* exceptionInfo )
{
if ( exceptionInfo )
{
EXCEPTION_RECORD* er = exceptionInfo->ExceptionRecord;
if ( er )
{
qWarning() << "Windows exception: " << er->ExceptionCode;
}
}
exit( 4 );
return EXCEPTION_EXECUTE_HANDLER;
}
int outOfMemory( size_t )
{
qWarning() << "Out of memory";
exit( 5 );
return 0;
}
#endif
Application::Application( int& argc, char** argv )
: QApplication( argc, argv )
{
#ifdef Q_OS_WIN
SetUnhandledExceptionFilter( exceptionFilter );
_set_new_handler( outOfMemory );
#endif
...
}
As per https://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus . Still no luck. Any ideas?
I am using Qt 5.15.2 on Windows 10.

Grpc access violation on client

I'm in the process of messing around with GRPC. Currently I'm using a C# web application as my GRPC server and I'm using a C++ console application as the client.
I was able to successfully connect and communicate with the server with no issue. The problem arises when
I exit the C++ console client application. Upon exiting an Access Violation is thrown.
Stack trace
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body
MeterReaderClientCpp.exe!__acrt_lock
ntdll.dll!RtlpWaitOnCriticalSection()
ntdll.dll!RtlpEnterCriticalSectionContended()
ntdll.dll!RtlEnterCriticalSection()
MeterReaderClientCpp.exe!__acrt_lock(__acrt_lock_id _Lock) Line 55
MeterReaderClientCpp.exe!_free_dbg(void * block, int block_use) Line 1019
MeterReaderClientCpp.exe!free(void * block) Line 32
MeterReaderClientCpp.exe!gpr_free(void * p) Line 53
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::destroy_thread() Line 142
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::Join() Line 112
MeterReaderClientCpp.exe!grpc_core::Thread::Join() Line 147
MeterReaderClientCpp.exe!gc_completed_threads() Line 74
MeterReaderClientCpp.exe!stop_threads() Line 331
MeterReaderClientCpp.exe!grpc_timer_manager_set_threading(bool threaded) Line 351
MeterReaderClientCpp.exe!grpc_shutdown_internal_locked() Line 175
MeterReaderClientCpp.exe!grpc_shutdown_internal(void * __formal) Line 208
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body(void * v) Line 128
GRPC Client
int main( )
{
using namespace MeterReaderWeb::Services;
using namespace google::protobuf::util;
using namespace google::protobuf;
std::cout << "Press enter\n";
std::cin.ignore( );
std::cout << "Calling Grpc service\n";
std::fstream file{ R"(C:\Certificates\certificate.cer)", std::ios::in | std::ios::beg };
if ( !file.is_open( ) )
{
std::cerr << "Failed to open file\n";
return 1;
}
std::stringstream buffer;
buffer << file.rdbuf( );
grpc::SslCredentialsOptions options;
options.pem_root_certs = buffer.str( );
auto credentials{ grpc::SslCredentials( options ) };
auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
auto stub{ MeterReadingService::NewStub( channel ) };
ReadingPacket packet;
packet.set_status( ReadingStatus::METER_READER_SUCCESS );
packet.set_notes( "Here are some random notes" );
auto message{ packet.add_readings( ) };
message->set_customer_id( 1 );
message->set_reading_value( 10001 );
auto timestamp{ message->mutable_reading_time( ) };
timestamp->CopyFrom( TimeUtil::GetCurrentTime( ) );
grpc::ClientContext context;
StatusMessage response;
if ( auto status{ stub->AddReading( &context, packet, &response ) }; status.ok( ) )
{
std::cout << "Added reading successfully\n";
auto responseStatus{ response.status( ) };
if ( responseStatus == ReadingStatus::METER_READER_SUCCESS )
{
std::cout << "Server status: success\n"
<< "Message: " << response.message( ) << '\n';
}
}
else
{
std::cerr << "Error: " << status.error_message( ) << '\n';
std::cerr << "Error Details: " << status.error_details( ) << '\n';
}
std::cin.ignore( );
}
I heavily used the GRPC route_guide_client.cc as a guide to help me write the above application.
I've tried adding calls to both grpc_init( ) and grpc_shutdown( ) even though their client examples don't contain either calls. But adding those had no effect.
What (if anything) am I missing here? Did I forget to call/populate something that the framework is attempting to clean up upon application exit?
OK I believe I've found what was causing the issue.
In my original post I said:
I've tried adding calls to both grpc_init( ) and grpc_shutdown( ) even though
the client examples don't contain either calls. But
adding those had no effect."
This was true, but after re-reading the documentation for grpc_shutdown( ) i noticed this (emphasis mine):
The last call to grpc_shutdown will initiate cleaning up of grpc
library internals, which can happen in another thread. Once the
clean-up is done, no memory is used by grpc, nor are any instructions
executing within the grpc library. Prior to calling, all application
owned grpc objects must have been destroyed.
This is where I think I went wrong. I was calling grpc_shutdown() while I still had grpc objects in scope. To correct I scoped the grpc objects and then called grpc_shutdown() once that scope was exited. This seems to have corrected the issue.
New Grpc Client
int main( )
{
std::cout << "Press enter\n";
std::cin.ignore( );
std::cout << "Calling Grpc service\n";
grpc_init( );
{ // <- Intentionally added scope here.
grpc::SslCredentialsOptions options;
if ( auto certificate{ ReadCertificate( ) } )
options.pem_root_certs = std::move( certificate ).value( );
else return 1;
auto credentials{ grpc::SslCredentials( options ) };
auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
auto stub{ MeterReadingService::NewStub( channel ) };
std::cout << "Sending single packet\n";
SendPacket( stub.get( ), 8000 );
std::cout << "Sending multiple packets\n";
StreamDiagnostics( stub.get( ), 3 );
}
std::cout << "Shutting down library\n";
grpc_shutdown_blocking( );
std::cout << "Shut down complete press enter to exit\n";
std::cin.ignore( );
}

Boost async server buffer error

I am trying to make a server & client in boost asio. Currently I am receiving this error. Can you point me what I am doing wrong?
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
// Forward declaration
class ASyncConnectionMT;
class ASyncEchoServerMT;
// Typedef for the buffer type (shared_ptr)
typedef boost::array < char , 65536 > Buffer;
typedef boost::shared_ptr < Buffer > BufferPtr;
// Typedef for the ASyncConnectionMT shared_ptr
// Typedef for the ASyncEchoServerMT shared_ptr
// Derived from "enable_shared_from_this" so the 'this' object can
// be passed as shared_ptr to the callback function
typedef boost::shared_ptr < ASyncConnectionMT > ASyncConnectionMTPtr;
typedef boost::shared_ptr < ASyncEchoServerMT > ASyncEchoServerMTPtr;
// Class the handles the client
class ASyncConnectionMT : public::boost::enable_shared_from_this<ASyncConnectionMT>
{
private: // The socket class for communication.
boost::asio::ip::tcp::socket m_socket;
// Strand object to synchronise calling handlers. Multiple threads might acces the socked
// at the same time since send and recieve are started asynchronously at the same time
boost::asio::strand m_strand;
public: // Constructor with the IO service to use
ASyncConnectionMT ( boost::asio::io_service& ios) : m_socket(ios), m_strand (ios)
{
}
// Retrieve the socked used by this connection
// Need to be passed to acceptor.accept() function
boost::asio::ip::tcp::socket& Socket()
{
return m_socket;
}
// Start handling the connection
void Start()
{
std:: cout << m_socket.remote_endpoint() << ": Connection accepted" << std:: endl ;
StartReceiving() ;
}
// Start receiving data
void StartReceiving()
{
// Create receive buffer
BufferPtr receiveBuffer ( new Buffer ) ;
// Start async read, must pass 'this' as shared_ptr, else the
// 'this' object will be destroyed after leaving this function
async_write ( m_socket, boost::asio::buffer ( *receiveBuffer ) , m_strand.wrap ( boost::bind ( &ASyncConnectionMT::HandleReceived, shared_from_this() ,
receiveBuffer , boost::asio::placeholders::error ,
boost::asio::placeholders::bytes_transferred ) ) ) ;
}
// Handle received data
void HandleReceived ( BufferPtr receiveBuffer , const boost::system::error_code& ec , size_t size)
{
if (!ec)
{
// Print received message
std:: cout << m_socket.remote_endpoint() << ": Message received: " << std:: string (receiveBuffer -> data() , size ) << std:: endl ;
// Convert to uppercare. We can't use the same buffer because that could be
// overwritten by another recieve
// UPD -> boost shared_ptr<TBuffer> sendBuffer(new TBuffer());
BufferPtr sendBuffer ( new Buffer ) ;
for ( size_t i=0 ; i!=size ; i++ )
{
(( &sendBuffer )[i]) = toupper (( &receiveBuffer )[i]) ;
}
// Start sending reply, must pass 'this' as shared_ptr, else the 'this' object will be
// destroyed after leaving this function. We pass the buffer as shared_ptr to the handler
// so the buffer is still in memory after sending is complete. Without it, the buffer could
// be deleted before the send operation is complete. The Handle Set is now synchronised via the strand.
async_write ( m_socket, boost::asio::buffer ( *sendBuffer , size ) , m_strand.wrap ( boost::bind ( &ASyncConnectionMT::HandleSent ,
shared_from_this() , sendBuffer ,
boost::asio::placeholders::error ,
boost::asio::placeholders::bytes_transferred ) ) ) ;
// Start receiving next bit
StartReceiving() ;
}
else if ( ec == boost::asio::error::eof)
{
// Client disconnected. Close the socket.
std:: cout << m_socket.remote_endpoint() << ": Connection closed ( handle received )" << std:: endl;
m_socket.close();
}
}
// Handle for when the data si sent
void HandleSent ( BufferPtr sendBuffer , const boost::system::error_code& ec , size_t size)
{
if (!ec)
{
// Start receiving again
StartReceiving() ;
}
else if ( ec == boost::asio::error::eof)
{
// Client disconnected. Close the socket.
std:: cout << m_socket.remote_endpoint() << ": Connection closed ( handle received )" << std:: endl;
m_socket.close();
}
else
{
std:: cout << "Error: " << ec.message << std:: endl ;
}
}
};
I am receiving the following errors.
C3967 - boost::system::error_code::message': function call missing argument list; use '&'boost::system::error_code::message' to create a pointer to member
C2664 - 'toupper' : cannot convert parametor 1 from 'BufferPtr' to 'int'
C2512 - 'boost::array' : no appropriate default constructor available
C2039 - 'data' : is not a member of 'boost::shared_prt'
C2027 - use of undefined type 'boost::array '
pointer to incomplete class type is not allowed
no suitable conversion function from "BufferPtr" to "int" exists
incomplete type is not allowed
Thanks in advance.
You missed the include
#include <boost/array.hpp>
The toupper loop is wrong
((&sendBuffer)[i]) = toupper((&receiveBuffer)[i]);
should be more like
((*sendBuffer)[i]) = toupper((*receiveBuffer)[i]);
or even more like
std::transform(receiveBuffer->begin(), receiveBuffer->end(), sendBuffer->begin(), static_cast<int(&)(int)>(std::toupper));
Pro tip: consider using unsigned char in the buffer to avoid unwanted sign extension when passing int to_upper
((*sendBuffer)[i]) = toupper(static_cast<unsigned char>((*receiveBuffer)[i]));
like the comment (and the compiler message) says:
std::cout << "Error: " << ec.message << std::endl;
should be
std::cout << "Error: " << ec.message() << std::endl;
Then it compiles. No guarantees it does what you expect (I haven't read the code)

Adding error_info to std::exception

I'm integrating boost::exception into existing code. Some of the code now uses BOOST_THROW_EXCEPTION, but some might still throw standard std::exception.
I want to add error_info at an intermediary catch site. According to the docs, if the exception is a boost::exception, I can just do this:
try {
do_something()
}
catch( boost::exception & e ) {
e << boost::errinfo_file_name(file_name);
throw;
}
But that will only add the info to the boost exceptions. I want to add it to the std::exception as well. What's the cleanest way to do that? Here's one way, but it results in some code duplication:
try {
do_something()
}
catch( boost::exception & e ) {
e << boost::errinfo_file_name(file_name);
throw;
}
catch( std::exception & e ) {
throw enable_error_info(e) << boost::errinfo_file_name(file_name);
}
Is there a method that's equivalent to "give me the current exception as a boost exception, or create a boost exception out of it if it isn't one"?
EDIT: boost::enable_error_info() kinda does that but returns a copy of the original exception, which slices off the boost::exception part of the exception I'm catching. Case in point:
int main()
{
try {
try {
BOOST_THROW_EXCEPTION( std::runtime_error( "foo" ) );
}
catch( std::exception & e ) {
std::cerr << e.what() << std::endl; // "foo"
if( const char* const* function = boost::get_error_info<boost::throw_function>(e) ) std::cerr << *function << std::endl; // "int main()"
throw boost::enable_error_info(e) << boost::errinfo_file_name("bar");
}
}
catch( std::exception & e ) {
std::cerr << e.what() << std::endl; // "std::exception"
if( const char* const* function = boost::get_error_info<boost::throw_function>(e) ) std::cerr << *function << std::endl; // NOTHING
}
return 0;
}
EDIT: I tried using boost::current_exception(), and it slices things off too. Basically, any attempt to copy an exception will loose some of the data because of the slicing caused by multiple inheritance. Same reason as why the docs say you should always rethrow using throw instead of throw e. So I really don't want to incur any copying unless it's necessary.
Ideally, I'd like to write the following, where current_exception_as_boost_exception() returns a reference to the current exception if it is already a boost::exception, otherwise returns the result of calling boost::enable_error_info on it.
try {
do_something()
}
catch( std::exception & e ) {
throw current_exception_as_boost_exception() << boost::errinfo_file_name(file_name);
}
Is that what boost::enable_current_exception is for? It's really unclear what its purpose is, and it's not used in any of the tutorials.
Here is a solution that does what I want. But if feels like I'm reinventing something here. Isn't there a built-in way to achieve the same thing?
struct rethrow
{
rethrow()
{
try{ throw; }
// Already a boost::exception
catch( boost::exception& ) {}
// Something else. Make it a boost::exception
catch( ... ) { ptr = boost::current_exception(); }
}
template<class T>
rethrow const& operator<<( const T& t ) const
{
try
{
re();
}
catch( boost::exception& e )
{
e << t;
}
return *this;
}
~rethrow()
{
re();
}
private:
void re() const
{
if( !ptr ) throw;
else boost::rethrow_exception( ptr );
}
boost::exception_ptr ptr;
};
int main()
{
try {
try {
throw std::runtime_error( "foo" ); // or BOOST_THROW_EXCEPTION( std::runtime_error( "foo" ) );
}
catch( std::exception & e ) {
rethrow() << boost::errinfo_file_name("bar");
}
}
catch( std::exception & e ) {
std::cerr << __LINE__ << ": caught " << e.what() << std::endl; // "caught foo"
if( const char* const* function = boost::get_error_info<boost::throw_function>(e) ) std::cerr << __LINE__ << ": throw from " << *function << std::endl; // "throw from int main()" (when using BOOST_THROW_EXCEPTION)
if( std::string const* fileName = boost::get_error_info<boost::errinfo_file_name>(e) ) std::cerr << __LINE__ << ": trying to open " << *fileName << std::endl; // "trying to open bar"
}
return 0;
}

Xerces thread safety?

taken from here:
http://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6
When two or more parser instances exist in a process, the instances can be used
concurrently, without external synchronization. That is, in an application containing two
parsers and two threads, one parser can be running within the first thread concurrently with
the second parser running within the second thread.
But the below code fails whenever the QMutex is commented and does not whenever it is used.
bool reports::validateSchema( QString fileName )
{
// QMutexLocker lock( &xercesMutex );
try
{
XMLPlatformUtils::Initialize();
}
catch(...)
{
this->throw_report_exception(__FILE__,__LINE__,__TIME__,__DATE__,"reports::validateSchema",
"unable to initialize Xerces Plateform");
return false;
}
const char* const xsd = "full absloute path to .xsd ==> hard written";
XercesDOMParser* parser = new XercesDOMParser();
try
{
parser->setValidationSchemaFullChecking(true);
parser->setDoSchema(true);
parser->setDoNamespaces(true);
parser->setValidationConstraintFatal(true);
parser->setValidationScheme(XercesDOMParser::Val_Auto);
ParserErrorHandler errHandler;
parser->setErrorHandler(&errHandler);
parser->cacheGrammarFromParse(true);
parser->loadGrammar(xsd,Grammar::SchemaGrammarType,true);
parser->parse(fileName.toStdString().c_str());
std::cout << parser->getErrorCount() << std::endl;
if(parser->getErrorCount()!=0)
{
return false;
}
}
catch (const XMLException& toCatch)
{
char* message = XMLString::transcode(toCatch.getMessage());
std::cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
return false;
}
catch (const DOMException& toCatch)
{
char* message = XMLString::transcode(toCatch.msg);
std::cout << "Exception message is: \n"
<< message << "\n";
XMLString::release(&message);
return false;
}
catch (...)
{
std::cout << "Unexpected Exception \n" ;
return false;
}
delete parser;
XMLPlatformUtils::Terminate();
return true;
}
What am I missing ?
The functions get executed hundreds of times and at some point, I'm getting a segfault from either:
XercesDOMParser* parser = new XercesDOMParser();
or
parser->loadGrammar(xsd,Grammar::SchemaGrammarType,true);
A quote from the same FAQ answer you refer to:
The application also needs to guarantee that the XMLPlatformUtils::Initialize() and
XMLPlatformUtils::Terminate() methods are called from the same thread (usually the
initial thread executing main()) or proper synchronization is performed by the application
if multiple threads call XMLPlatformUtils::Initialize() and XMLPlatformUtils::Terminate()
concurrently.