expat exception handling - c++

I had been trying hard to figure out why the exceptions thrown from StartElement event handler are not being caught by my application which makes use of expat parser( in C). The application just terminates saying that it cannot find catch blocks, though I have all the catch blocks in place. It is just that since exceptions are being thrown from my own event handlers, XML_Parse API of expat is unable to pass it on to my code where I have all the catch blocks. One of the stackoverflow user with name 'Michael Anderson" suggested to rebuild expat lib with necessary gcc flags to make expat lib handle exceptions. Can someone let me know what flags are those? Or Suggest a better way out to handle errors in event handlers like startelement, endelement etc.
I somehow want XML_Parse API to return 0 if I encounter any exception in my registered event handlers. Please help. Thanks in advance.
Here is the code:
try
{
if( ! XML_Parse(.....) )
{
throw exception;
}
}
catch(...)
{
}
In the working scenario, if XML_Parse encounters a malformed xml file, it promptly returns zero, and I get into if block and throw exception, and it is caught fine.
But in the problematic case, the exceptions are being thrown from the event handlers but my application dumps core, and core stack says that it cannot find catch and finally calling std::terminate and abort.
Now, how do I make XML_Parse to return zero when I want to throw user defined exception from event handlers?

As per expat.h, you should invoke XML_StopParser(parser, 0) when you encounter an error in your handler that warrants aborting the parse.
XML_Parse will then return XML_FALSE. At that point you can invoke your application-specific error handling

Related

How to catch exceptions thrown by the ConnectAsync method of MessageWebSocket?

I'm implementing an UWP application for the HoloLens which streams a point cloud over a MessageWebSocket to a companion PC. If I launch the app on the HoloLens while the server on the companion PC is not yet running, calling the ConnectAsync method of MessageWebSocket triggers an exception (because it can't connect to the server) which causes my app to crash. However, I can't figure out how to catch this exception.
Inspired by the example code shown in the official documentation of MessageWebSocket, this is a small sample which reproduces the issue:
void TryConnectToWebsocket()
{
Windows::Networking::Sockets::MessageWebSocket^ websocket = ref new Windows::Networking::Sockets::MessageWebSocket();
websocket->Control->MessageType = Windows::Networking::Sockets::SocketMessageType::Utf8;
try
{
::OutputDebugString(L"Trying to connect...\n");
auto connectTask = Concurrency::create_task(websocket->ConnectAsync(ref new Windows::Foundation::Uri(L"ws://192.168.0.38:9090")));
connectTask.then([this, websocket]
{
::OutputDebugString(L"Connected successfully!");
websocket->Close(1000, "Application caused the connection to close.");
});
}
catch (...)
{
::OutputDebugString(L"Couldn't connect to websocket!");
}
}
Please note, that the original example code from the docs catches exceptions of type Platform::Exception. I chose to catch exceptions of all types in this code snippet to assert that I don't miss the exception in case it is not a Platform::Exception (or a subtype of it).
If I run this code snippet (without the server being started), I would expect the following console output:
Trying to connect...
Couldn't connect to the websocket!
However, what I get is the following: (Console outputs about loaded and unloaded DLLs have been left out. Some of the messages describing what went wrong were originally in German, so I've translated them.)
Trying to connect...
Exception thrown at 0x76B34592 (KernelBase.dll) in Test.exe: WinRT originate error - 0x80072EFD : 'A connection with the server could not be established.'.
Exception thrown at 0x76B34592 in Test.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x0C5AE500. HRESULT:0x80072EFD The message for this error code could not be found.
WinRT information: A connection with the server could not be established.
Stack trace:
>[External Code]
As you can see, the catch block isn't being executed at all. Furthermore, the very short and unprecise stack trace makes it appear as if the exception is thrown somewhere in a background thread where I don't even have a chance of catching it.
I'd really like to handle this exception instead of having the application crash. Is there any way how I can do this?
From the official sample, it doesn't put every operation that might throw within a try…catch block. Instead, it adds a task-based continuation at the end of the chain and handles all errors there. You can try the following code to catch the exception.
create_task(messageWebSocket->ConnectAsync(ref new Windows::Foundation::Uri(L"ws://192.168.0.38:9090")))
.then([this](task<void> previousTask)
{
try
{
previousTask.get();
::OutputDebugString(L"Connected successfully!");
websocket->Close(1000, "Application caused the connection to close.");
}
catch (Exception^ ex)
{
::OutputDebugString(L"Couldn't connect to websocket!");
}
});

Poco - failure to openApplication log causes subsystem shutdown failure

I'm using Poco 1.6.0 and the Util::ServerApplication structure.
At the start of int main(const ArgVec& args) in my main class, I redirect all the logging to a file:
Poco::AutoPtr<Poco::FileChannel> chanFile = new Poco::FileChannel;
chanFile->setProperty("path", "C:\\doesnotexist\\file.log");
Poco::Util::Application::instance().logger().setChannel(chanFile);
If the log file cannot be opened, this causes an exception to be thrown, which I catch, and return an error code from main(). The Application::run() code in Poco's Application.cpp then calls Application::uninitialize().
The implementation of Application::uninitialize()iterates through each SubSystem executing that subsystem's uninitialize().
But one of those is LogFile::uninitialize(), which causes the following message to be logged: Uninitializing subsystem: Logging Subsystem.
When it attempts to log that message, an exception is thrown since the log file could not be opened (for the same reason as before). That exception is caught somewhere in Poco's code and it attempts to log an error, which causes an exception, and that one finally terminates the program.
How should I deal with this issue? E.g. is it possible to tell the logging subsystem to not throw any exceptions?
There seems to be a greater issue too; if any subsystem uninitialize() throws, this will cause execution to leave the subsystem shutdown loop in Application.cpp , so other subsystems will not have a chance to shut down either.
You should make sure that the path exist before setting up the file channel, e.g.:
if (Poco::File("C:\\doesnotexist").exists())
{
Poco::AutoPtr<Poco::FileChannel> chanFile = new Poco::FileChannel;
chanFile->setProperty("path", "C:\\doesnotexist\\file.log");
Poco::Util::Application::instance().logger().setChannel(chanFile);
}
Application::unitialize() will loop through subsystems and log iterations as debug messages - the idea is to catch problems before release.
UPDATE: as pointed in the comments, the directory may exist at the time of the check but may not exist (or not be accessible) afterwards, when logging actually happens. There is nothing in Poco that shields user from that; so, you will have to make sure the directory exists and is accessible throughout the lifetime of the FileChannel using it. I have not found this to be an obstacle in practice. I did find the initial non-existence of a directory to be an annoying problem and there is a proposal for addition of such (optional/configurable) feature but it has not been scheduled yet for inclusion in upcoming releases.

storagefile::ReadAsync exception in c++/cx?

I have been trying to use c++/cx StorageFile::ReadAsync() to read a file in a store-apps, but it always return an invalid params exception no matter what
// "file" are returned from FileOpenPicker
IRandomAccessStream^ reader = create_task(file->OpenAsync(FileAccessMode::Read)).get();
if (reader->CanRead)
{
BitmapImage^ b = ref new BitmapImage();
const int count = 1000000;
Streams::Buffer^ bb = ref new Streams::Buffer(count);
create_task(reader->ReadAsync(bb, 1, Streams::InputStreamOptions::None)).get();
}
I have turn on all the manifest capabilities and added "file open picker" + "file type association" for Declarations. Any ideas ? thanks!
ps: most solutions I found is for C#, but the code structure are similar...
If this code is executing on the UI thread (or in any other Single Threaded Apartment, or STA), then the calls to .get() will throw if the tasks have not yet completed, because the call to .get() would block the thread. You must not block the UI thread or any other STA, and when compiling with C++/CX support enabled, the libraries enforce this.
If you turn on first chance exception handling in the debugger (Debug -> Exceptions..., check the C++ Exceptions check box), you should see that the first exception to be thrown is an invalid_operation exception, from the following line in <ppltasks.h>:
// In order to prevent Windows Runtime STA threads from blocking the UI, calling
// task.wait() task.get() is illegal if task has not been completed.
if (!_IsCompleted() && !_IsCanceled())
{
throw invalid_operation("Illegal to wait on a task in a Windows Runtime STA");
}
The "invalid parameter" you are reporting is the fatal error that is caused when this exception reaches the ABI boundary: the debugger is notified that the application is about to terminate because this exception was unhandled.
You need to restructure your code to use continuations, using task::then, as described in the article Asynchronous Programming in C++ Using PPL
Just to make sure you understand the async pattern, what is happening in your code is that you call create_task and immediately after that task has started you are trying to get the result with .get(). Calls to .get() will throw immediately if the task is still running or the file could not be found. Therefore, the correct way of structuring this is using a .then on your file task, ensuring that you have the result of this task before starting the next one.
create_task(file->OpenAsync(FileAccessMode::Read)).then([](IRandomAccessStream^ reader)
{
//do stuff with the reader
});
At that point the reader is available so you can do whatever you want to, even start a new task.
Also, it is possible that the call to OpenAsync is failing cause the file is empty, I would add a try catch block to the previous task, the one that gets the file, just to make sure that's not the problem.

how should you handle file open error in a thread without cancellation?

I have an service application that reads a config file containing a list of files to open. The problem is when it doesn't find the file in the directory, it throws an exception thus cancelling the thread and stopping the service application as well.
Here's a code block of the function being called in a thread:
FILE* file_;
ServiceApp::File::File( const char* filename, const char* mode) :
file_(fopen(filename, mode))
{
if( !file_ )
{
// throwing will stop the service when file doesn't exist, what work around could we do?
throw std::runtime_error("file open failure");
}
Question:
How do we prevent this from happening so that when a file listed in the config file is not found in the directory, the application would just ignore it and continue with the process?
I would recommend using std::async. If a function throws which is run via std::async, the exception will be saved in the std::future. I will be rethrown when you call std::future::get(). However if you don't do that, it will just be "ignored" and thus you application will keep on running.
Example:
auto lambda = [] {
throw std::runtime_error("error");
};
auto handle = std::async(std::launch::async, lambda);
For more info on std::async read this.
The simplest way is to put try / catch statements to surround the block of code that processes the file.
There is a high chance that you will encounter other exceptions being thrown in other special cases (e.g. when reading network file that disappeared during reading), so check code for other exceptions carefully
The easiest would be just to try-catch your own exception, in the thread, then check for it being that exception (to ignore it), and rethrowing if it's some other exception.
I'm not sure if it's possible to add info to the exception where thrown or is it legacy code? In the latter case you'll have to resort to string comparison, which of course is ugly. Anyway.
// pseudo-code
while(GotFilesInQueue())
{
try
{
LoadNextFile();
}
catch(std::exception& e)
{
if(!IgnoreExceptionPredicate(e))
{
throw;
}
}
}
On Rethrowing

Handling Exceptions in a critical application that should not crash

I have a server application which I am debugging which basically parses scripts (VBscript, Python, Jscript and SQl) for the application that requests it.
This is a very critical application which, if it crashes causes havoc for a lot of users. The problem I am facing is how to handle exceptions so that the application can continue and the users know if something is wrong in their scripts.
An example: In the SQL scripts the application normally returns a set of values (Date, Number, String and Number). So the scripts have to have a statement at the end as such:
into dtDate, Number, Number, sString. These are values that are built into the application and the server application knows how to interpret these. These fields are treated in the server app as part of an array. The return values should normally be in a specific order as the indexes for these fields into the array are hardcoded inside the server application.
Now when a user writing a script forgets one of these fields, then the last field (normally string) throws an IndexOutofBoundsException.
The question is how does one recover from exceptions of this nature without taking down the application?
Another example is an error in a script for which no error parsing message can be generated. These errors just disappear in the background in the application and eventually cause the server app to crash. The scripts on which it fails don't necessarily fail to execute entirely, but part of it doesn't execute and the other parts do, which makes it look fairly odd to a user.
This server app is a native C++ application and uses COM technologies.
I was wondering if anyone has any ideas on what the best way is to handle exceptions such as the ones described above without crashing the application??
You can't handle problems like this with exceptions. You could have a top-level catch block that catches the exception and hope that not too much state of the program got irrecoverably munched to try to keep the program alive. Still doesn't make the user happy, that query she is waiting for still doesn't run.
Ensuring that changes don't destabilize a critical business app requires organization. People that sign-off on the changes and verify that they work as intended before it is allowed into production. QA.
since you talk about parsing different languages, you probably have something like
class IParser //parser interface
{
virtual bool Parse( File& fileToParse, String& errMessage ) = 0;
};
class VBParser : public Parser
class SQLParser : public Parser
Suppose the Parse() method throws an exception that is not handled, your entire app crashes. Here's a simplified example how this could be fixed at the application level:
//somewhere main server code
void ParseFileForClient( File& fileToParse )
{
try
{
String err;
if( !currentParser->Parse( fileToParse, err ) )
ReportErrorToUser( err );
else
//process parser result
}
catch( std::exception& e )
{
ReportErrorToUser( FormatExceptionMessage( err ) );
}
catch( ... )
{
ReportErrorToUser( "parser X threw unknown exception; parsing aborted" );
}
}
If you know an operation can throw an exception, then you need to add exception handling to this area.
Basically, you need to write the code in an exception safe manner which usually uses the following guidelines
Work on temporary values that can throw exceptions
Commit the changes using the temp values after (usually this will not throw an exception)
If an exception is thrown while working on the temp values, nothing gets corrupted and in the exception handling you can manage the situation and recover.
http://www.gotw.ca/gotw/056.htm
http://www.gotw.ca/gotw/082.htm
It really depends on how long it takes to start up your server application. It may be safer to let the application crash and then reload it. Or taking a cue from Chrome browser run different parts of your application in different processes that can crash. If you can safely recover an exception and trust that your application state is ok then fine do it. However catching std::exception and continuing can be risky.
There are simple to complex ways to baby sit processes to make sure if they crash they can be restarted. A couple of tools I use.
bluepill http://asemanfar.com/Bluepill:-a-new-process-monitoring-tool
pacemaker http://www.clusterlabs.org/
For simple exceptions that can happen inside your program due to user errors,
simply save the state that can be changed, and restore it like this:
SaveStateThatCanBeAlteredByScript();
try {
LoadScript();
} catch(std::exception& e){
RestoreSavedState();
ReportErrorToUser(e);
}
FreeSavedState();
If you want to prevent external code from crashing (possible untrustable code like plugins), you need an IPC scheme. On Windows, I think you can memory map files with OpenFile(). On POSIX-systems you can use sem_open() together with mmap().
If you have a server. You basically have a main loop that waits for a signal to start up a job. The signal could be nothing and your server just goes through a list of files on the file system or it could be more like a web server where it waits for a connection and executes the script provided on the connection (or any thing like that).
MainLoop()
{
while(job = jobList.getJob())
{
job.execute();
}
}
To stop the server from crashing because of the scripts you need to encapsulate the external jobs in a protected region.
MainLoop()
{
// Don't bother to catch exceptions from here.
// This probably means you have a programming error in the server.
while(job = jobList.getJob())
{
// Catch exception from job.execute()
// as these exceptions are generally caused by the script.
try
{
job.execute();
}
catch(MyServerException const& e)
{
// Something went wrong with the server not the script.
// You need to stop. So let the exception propagate.
throw;
}
catch(std::exception const& e)
{
log(job, e.what());
}
catch(...)
{
log(job, "Unknown exception!");
}
}
}
If the server is critical to your operation then just detecting the problem and logging it is not always enough. A badly written server will crash so you want to automate the recovery. So you should write some form of heartbeat processes that checks at regular intervals if the processes has crashed and if it has automatically restart it.