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

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!");
}
});

Related

Get "The application called an interface that was marshalled for a different thread" error while getting content from Clipboard

Aim: Get content from the clipboard using C++/WinRT APIs.
Problem:
Since I'm just testing this API, I tried to code a simple console app with the blocking get() method on Clipboard's async text getter. However, I'm getting the "The application called an interface that was marshalled for a different thread" error when debugging. I also tried to init apartments as single threaded apartment (STA), but I guess it's not allowed because another assertion error (!is_sta()) is thrown. Now I'm just wondering why this error is thrown when calling get and how to retrieve the content from clipboard in my console app. (I saw some examples (mostly GUI apps) are using coroutines which I'm not familiar with though.)
Code:
using namespace winrt::Windows::ApplicationModel::DataTransfer;
int main()
{
init_apartment();
hstring text{ Clipboard::GetContent().GetTextAsync().get() };
std::wcout << text.c_str() << std::endl;
}
Error message:
Exception thrown at 0x7659ACC2 (KernelBase.dll) in test-clipboard.exe: WinRT originate error - 0x8001010E : 'The application called an interface that was marshalled for a different thread.'.
'test-clipboard.exe' (Win32): Loaded 'C:\Windows\SysWOW64\bcrypt.dll'.
Exception thrown at 0x7659ACC2 in test-clipboard.exe: Microsoft C++ exception: winrt::hresult_wrong_thread at memory location 0x010FF818.
Unhandled exception at 0x7659ACC2 in test-clipboard.exe: Microsoft C++ exception: winrt::hresult_wrong_thread at memory location 0x010FF818.
Sincerely appreciate your help. Thanks.
The WinRT clipboard APIs can only be called from a UI thread with a CoreWindow. See notes In the documentation. You can just use the regular Win32 clipboard APIs in your console app.

Is there a way to direct swagger codegen to generate task based continuations for tasks to catch exception thrown by cpprest?

I have swagger codegen generated c++ code with cpprest that makes some server calls.
Issue that I am facing:
If cpprest http request returns any error code (4xx or 5xx), I get the following crash when I run my program in CentOS Linux. If cpprest http request returns a success, my program does not crash.
Callstack of the crash:
0x00007fe97b987207 libc.so.6!gsignal(+0x37)
0x00007fe97b9888f8 libc.so.6!abort(+0x147)
0x0000000007f2478b MyServer!abort_message()
0x0000000007f24ae1 MyServer!demangling_terminate_handler()()
0x0000000007f24983 MyServer!std::__terminate(void (*)())()
0x0000000007f24a05 MyServer!std::terminate()(+0x44)
0x00007fe97a417734 libstdc++.so.6!_ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE(+0x73)
0x00007fe97c9fdc05 libMyLibrary.so!_ZN4pplx7details16_ExceptionHolder21_RethrowUserExceptionEv(+0x24)
0x00007fe97c9fea05 libMyLibrary.so!_ZN4pplx7details15_Task_impl_base5_WaitEv(+0x2e4)
0x00007fe97c9faab6 libMyLibrary.so!_ZN5Test18MyManager16CallServerApi1EPKwS2_ibS2_Pwm(+0x615)
Explanation:
Basically, MyLibrary shared object has a function CallServerApi1() that calls a function in the swagger code gen called CallServerApi1() again, which makes a cpprest request.
The following code is inside CallServerApi1() function of MyApi class in swagger generated code:
return m_ApiClient->callApi(path, utility::conversions::to_string_t("POST"), queryParams, httpBody, headerParams, formParams, fileParams, requestHttpContentType)
.then([=](web::http::http_response response)
{
// 1xx - informational : OK
// 2xx - successful : OK
// 3xx - redirection : OK
// 4xx - client error : not OK
// 5xx - client error : not OK
if (response.status_code() >= 400)
{
//throw my exception with details in case http returned a error response code.
throw MyException(response.status_code()
, utility::conversions::to_string_t("error calling CallServerApi1: ") + response.reason_phrase()
, std::make_shared<std::stringstream>(response.extract_utf8string(true).get()));
}
return response.extract_string(); // If successfull return the response data
});
My code in MyLibrary has a try catch to catch the MyException thrown by the swagger generate code.
try
{
auto task = api.CallServerApi1();
task.wait();
if (task.is_done())
{
}
}
catch (const MyException& e)
{
string error = e.what();
int error = e.error_code().value();
}
I read here: https://learn.microsoft.com/en-us/cpp/parallel/concrt/exception-handling-in-the-concurrency-runtime?view=vs-2019 that states that
When you throw an exception in the body of a work function that you pass to a task object, the runtime stores that exception and marshals it to the context that calls concurrency::task::get or concurrency::task::wait.
and
When a task throws an exception, its task-based continuations are scheduled to run.
My understanding is that, since the swagger generated code has task based continuation, and the crash callstack has a line that states that the pplx is throwing a user exception
libMyLibrary.so!_ZN4pplx7details16_ExceptionHolder21_RethrowUserExceptionEv(+0x24)
It seems like cpprest is re-throwing an exception and it not being handled by the swagger generated code due to value-based continuation, and hence it crashes because libstdc++ standard is instructed to do so for rethrown exceptions. Can anyone shed light on this, whether this might be the case and if so, is there a way to inform swagger code gen to use task based continuations instead of value based, to allow the exception from cpprest to pass through and be handled inside the then() block ?

Need help loading Cortana VCD file on using C++ DirectX/XAML

I am adding Cortana to a DirectX/XAML Windwos 10 game. Every example I can find is given in C#, not C++. Normally this wouldn't be a problem, but apparently I'm not implementing it correctly in C++ and need some help with this one.
The purpose of this chunk of code is to load a VCD file which Cortana uses for my app-related voice commands. I have already created the VCD file using standard examples.
This is the specific C# code I'm having trouble implementing in C++:
var storageFile =
await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appx:///myvcdfile.xml"));
await
Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.
InstallCommandDefinitionFromStorageFileAsync(storageFile);
My attempted C++ implementation of this is:
Uri^ uri = ref new Uri("ms-appx:///myvcdfile.xml");
create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).then([](task<StorageFile^> t) {
StorageFile^ sfile = t.get();
Windows::ApplicationModel::VoiceCommands::VoiceCommandDefinitionManager::InstallCommandDefinitionsFromStorageFileAsync(sfile);
});
When I run this, no visible error is thrown (no immediate crash) but in the output window the following exceptions are thrown:
Exception thrown at 0x76473E28 (KernelBase.dll) in darksong.exe: 0x40080201: WinRT originate error (parameters: 0x8000000B, 0x00000040, 0x018BE280).
Exception thrown at 0x76473E28 (KernelBase.dll) in darksong.exe: 0x00000005: Access is denied.
Exception thrown at 0x76473E28 (KernelBase.dll) in darksong.exe: 0x000006D9: There are no more endpoints available from the endpoint mapper.
Exception thrown at 0x76473E28 (KernelBase.dll) in darksong.exe: 0x000006D9: There are no more endpoints available from the endpoint mapper.
Exception thrown at 0x76473E28 (KernelBase.dll) in darksong.exe: 0x40080201: WinRT originate error (parameters: 0x80004005, 0x00000013, 0x0EEAF160).
The "access is denied" error makes me think there is some issue opening the file itself, although if I purposely enter an invalid filename it's a completely different error which crashes, so I know it's finding the file but perhaps is having some issue actually accessing it?
Also, even if I exclude the "InstallCommandDefinitionsFromStorageFileAsync()" line The exceptions are all still thrown.
Any help is appreciated, thanks in advance!
You have certainly an error in your xml file (if you have set for exemple in command an item using PhraseList but you have forgot the PhraseList node in your xml)

expat exception handling

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

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.