microsoft / krabsetw

KrabsETW provides a modern C++ wrapper and a .NET wrapper around the low-level ETW trace consumption functions.
Other
588 stars 147 forks source link

Unhandled exception thrown by get_event_schema_from_tdh() in ut::forward_events() #161

Open ghost opened 3 years ago

ghost commented 3 years ago

get_event_schema_from_tdh() can throw an exception in case an error is returned by TdhGetEventInformation(). This exception is not handled in ut::forward_events() and will result in process termination. This happens before user callbacks are called so there is no way of setting up exception handling by the user.

ghost commented 3 years ago

This seems related to the changes introduced in the context of #143.

Had this happen on a Server 2012 R2 with .NET 3.5, 4, and 4.5 installed. I suppose it could also be non .NET related. Unfortunately I don't have the exact details.

What ever the cause, the exception should be handled in ut::forward_events(). Should it just be ignored? Should there be some error call back to let the caller handle problematic events?

kaaleksandr commented 2 years ago

Привет! Данная ситуация проявляется после освобождения объекта типа krabs::user_trace. После его освобождения сессия etw еще не завершена и вызываются функции trace::on_event, в этих функциях идет обращение к объекту krabs::user_trace, который уже освобожден, в следствии чего происходит необработанное исключение. Такая ситуация проявляется при частом создании новый сессий ETW, когда нужно сессию остановить и снова запустить. Решение данной проблемы: освобождать объект krabs::user_trace после выхода из метода krabs::user_trace::start.

swannman commented 2 years ago

I made changes in #174 and #175 to address a case that sounds like what you are describing.

Also sharing a translation of @kasandrk's helpful comment to make it accessible to English speakers:

Hey! This situation manifests itself after the release of an object of the krabs :: user_trace type. After its release, the etw session has not yet been completed and the trace :: on_event functions are called, in these functions the call to the krabs :: user_trace object, which has already been released, occurs, as a result of which an unhandled exception occurs. This situation occurs when new ETW sessions are often created, when you need to stop the session and start it again. The solution to this problem is to release the krabs :: user_trace object after exiting the krabs :: user_trace :: start method.

@fs-granma could you confirm whether this failure mode is still occurring in the latest release? Thanks!

kaaleksandr commented 2 years ago

example code:

std::thread* th1;
{
    krabs::user_trace trace(L"My Named Trace");

    th1 = new std::thread
    {
        [&]()
        {
            krabs::provider<> provider(krabs::guid(L"{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}"));

            provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context)
                {
                    for (;;)
                    {
                        krabs::schema schema(record, trace_context.schema_locator);
                        std::wcout << L"1) Event ID: " << schema.event_id() << std::endl;
                    }
                });

            trace.enable(provider);
            trace.start();
        }
    };

    Sleep(1000);
}

std::cout << "stop" << std::endl;
_getch();
kaaleksandr commented 2 years ago

forward_etw

ghost commented 2 years ago

@swannman, Looking at the code, it seems the exception thrown from https://github.com/microsoft/krabsetw/blob/79e8af192eaa2a3bfd6365238903bae91b796beb/krabs/krabs/ut.hpp#L241 is still unhandled as this is not a user callback.