-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stability fixes in native code #226
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -282,6 +282,12 @@ namespace krabs { | |
*/ | ||
void set_default_event_callback(c_provider_callback callback); | ||
|
||
template <typename U> | ||
void set_default_event_callback(U& callback); | ||
|
||
template <typename U> | ||
void set_default_event_callback(const U& callback); | ||
|
||
private: | ||
|
||
/** | ||
|
@@ -348,7 +354,8 @@ namespace krabs { | |
template <typename T> | ||
trace<T>::~trace() | ||
{ | ||
stop(); | ||
// Never throw in destructor | ||
try { stop(); } catch (...) {} | ||
} | ||
|
||
template <typename T> | ||
|
@@ -440,7 +447,30 @@ namespace krabs { | |
template <typename T> | ||
void trace<T>::set_default_event_callback(c_provider_callback callback) | ||
{ | ||
// C function pointers don't interact well with std::ref, so we | ||
// overload to take care of this scenario. | ||
default_callback_ = callback; | ||
} | ||
|
||
template <typename T> | ||
template <typename U> | ||
void trace<T>::set_default_event_callback(U& callback) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have an example of what you're trying to solve here? I don't think you should need these at all. template <typename T>
template <typename U>
void trace<T>::set_default_event_callback(U&& callback) This can bind to all flavors of parameters correctly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The same approach is used in |
||
{ | ||
// std::function copies its argument -- because our callbacks list | ||
// is a list of std::function, this causes problems when a user | ||
// intended for their particular instance to be called. | ||
// std::ref lets us get around this and point to a specific instance | ||
// that they handed us. | ||
default_callback_ = std::ref(callback); | ||
} | ||
|
||
template <typename T> | ||
template <typename U> | ||
void trace<T>::set_default_event_callback(const U& callback) | ||
{ | ||
// This is where temporaries bind to. Temporaries can't be wrapped in | ||
// a std::ref because they'll go away very quickly. We are forced to | ||
// actually copy these. | ||
default_callback_ = callback; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,7 +164,7 @@ namespace krabs { namespace details { | |
std::vector<BYTE> filterEventIdBuffer; | ||
auto filterEventIdCount = settings.provider_filter_event_ids_.size(); | ||
|
||
if (filterEventIdCount > 0) { | ||
if (filterEventIdCount > 0 && filterEventIdCount <= MAX_EVENT_FILTER_EVENT_ID_COUNT) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be an error condition that is bubbled up to the caller and then we can either:
I prefer throwing so it's obvious what went wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both variants not ideal. We limit the user's use of krabs filtering. In my case we just "turn off" system pre-filtration. We will get all events (even unneeded) from provider but have a chance to filter them from in callback. |
||
//event filters existing, set native filters using API | ||
parameters.FilterDescCount = 1; | ||
filterDesc.Type = EVENT_FILTER_TYPE_EVENT_ID; | ||
|
@@ -237,15 +237,18 @@ namespace krabs { namespace details { | |
|
||
// for MOF providers, EventHeader.Provider is the *Message* GUID | ||
// we need to ask TDH for event information in order to determine the | ||
// correct provider to pass this event to | ||
auto schema = get_event_schema_from_tdh(record); | ||
auto eventInfo = reinterpret_cast<PTRACE_EVENT_INFO>(schema.get()); | ||
for (auto& provider : trace.providers_) { | ||
if (eventInfo->ProviderGuid == provider.get().guid_) { | ||
provider.get().on_event(record, trace.context_); | ||
return; | ||
// correct provider to pass this event to. Don't throw in callback. | ||
try | ||
{ | ||
auto eventInfo = trace.context_.schema_locator.get_event_schema(record); | ||
for (auto& provider : trace.providers_) { | ||
if (eventInfo->ProviderGuid == provider.get().guid_) { | ||
provider.get().on_event(record, trace.context_); | ||
return; | ||
} | ||
} | ||
} | ||
catch (krabs::could_not_find_schema&) {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This exception should not be caught. How else will a caller know why the callback is not working? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And trace session will close without any chance to resume. In my case we can still handle event in default callback. May be adding an error_callback to trace object is a good idea? We can call it from catch. |
||
|
||
if (trace.default_callback_ != nullptr) | ||
trace.default_callback_(record, trace.context_); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you see this throw? I'd need to look to see how trace_manager can throw.
Usually, we don't want to catch everything. There's also implications for SEH callbacks that might have been set up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing an exception out of a destructor is dangerous. If another exception is already propagating the application will terminate.
ControlTrace(EVENT_TRACE_CONTROL_STOP) or CloseTrace() can return error inside stop(). Using SEH is to much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm aware that destructors shouldn't throw, however it's not a good pattern to just add "catch all" blocks in all the destructors. Catch what we expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. If we add error_callback to the trace object it may solve the user notification issue.