Conversation
|
Thanks! For this one, actually, I’m wondering if we should use C++/WinRT’s auto_revoke machinery. Since we are largely dealing with other WinRT objects and not manually bound std::functions, we can probably use more of the cool platform accordances. These auto_revokers get torn down during destruction, which ensures that a destructed TermControl has all of its handlers unbound before it becomes invalid. |
|
(There are a couple where we explicitly specify the tear down order, but those shouldn’t need to be weak.) |
Novice stuff
|
I'll start by rolling back the auto_revoke handlers that I changed to use weak_ref (didn't realize auto_revoke made the event safe), and if I see some easy wins for the others I'll rework them to. |
|
Thanks 😄 |
WinRT has some neat features
|
Was able to make one extra event auto_revoke, so all events |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| _root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this]() { | ||
| // Update our control settings | ||
| _ApplyUISettings(); | ||
| _root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis]() { |
There was a problem hiding this comment.
nit: you can [weakThis = get_weak()] if the weak ref is only going to be used in the lambda
There was a problem hiding this comment.
That form reads better. I'll include it in the next commit.
| if (auto control{ weakThis.get() }) | ||
| { | ||
| // Update our control settings | ||
| control->_ApplyUISettings(); |
There was a problem hiding this comment.
not 100% sure on how i feel about indirecting through control-> every time; in debug builds each one will be a call to winrt::com_ptr::operator->()...
but i do not know how much, if at all, I care. Thoughts?
There was a problem hiding this comment.
(we could capture weakThis,this and then only use this implicitly if the weak got locked. @zadjii-msft?)
There was a problem hiding this comment.
I prefer the way the weakThis,this lambdas read. All the control-> just clutters things, not mention your comment about winrt::com_ptr::operator->(). WinRT could almost use a class to support this form of lambda. It would be extensible to all the places where we're having trouble with the { this, pointer-to-member } event format. Anyways, I'll include the fix to these in the next revision commit.
There was a problem hiding this comment.
I think I prefer it like this - not capturing this at all makes it harder for us to accidentally do the wrong thing.
There was a problem hiding this comment.
I guess there's a "convenient" middle ground...
if (auto strongThis{ weakThis.get() })
{
auto& that{ *strongThis };
that->x;
that->y;
}
I am worried about the constant indirection through operator->... but at the same time, WRL::ComPtr literally is that for all com calls, sooooooooo maybe i should not be worried?
There was a problem hiding this comment.
It's just that this is a member function, but we have to write it in a weird way that makes it not look like a member function.
There was a problem hiding this comment.
Let me know which form to go with, and I'll include it in the next commit.
| localAutoScrollTimer.Stop(); | ||
| // _autoScrollTimer timer, now stopped, is destroyed. | ||
| } | ||
|
|
There was a problem hiding this comment.
i'm surprised tearing down the timers isn't necessary anymore, but I'm willing to believe it 😄
There was a problem hiding this comment.
Those Stop calls were only throwing in the event that TermControl was being destructed at the end of an event handler, which was strange. Could just wrap them in try-catch blocks if the Stop calls really should be there 🤔
There was a problem hiding this comment.
The most correct solution might be to make both the timers Tick events take a get_weak() as opposed to this, right? If we had done that from the start, we probably wouldn't have ever needed these lines...
|
Thanks for the reviews. I've pushed some changes. |
|
I'm closing and reopening to convince the CLA bot. |
zadjii-msft
left a comment
There was a problem hiding this comment.
I'm okay with this, but maybe we should make those Tick events take get_weak(). @mkitzan are you planning on making a pass for all the { this, &TermControl::EventHandler } instances?
| localAutoScrollTimer.Stop(); | ||
| // _autoScrollTimer timer, now stopped, is destroyed. | ||
| } | ||
|
|
There was a problem hiding this comment.
The most correct solution might be to make both the timers Tick events take a get_weak() as opposed to this, right? If we had done that from the start, we probably wouldn't have ever needed these lines...
|
Yeah, |
|
Hello @zadjii-msft! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
|
🎉 Handy links: |

Summary of the Pull Request
An asynchronous event handler capturing raw
thisinTermControlwas causing an exception to be thrown when a scroll update event occurred after closing the active tab. This PR replaces all non-auto_revoke lambda captures inTermControlto capture (and validate) awinrt::weak_refinstead of using rawthis.References
PR Checklist
Detailed Description of the Pull Request / Additional comments
TermControlis already a WinRT type so no changes were required to enable thewinrt::weak_reffunctionality. There was only one strange change I had to make. In the destructor's helper functionClose, I had to remove two calls toStopwhich were throwing under some circumstances. Fortunately, these calls don't appear to be critical, but definitely a spot to look into when reviewing this PR.Beyond scrolling, any anomalous crash related to the following functionality while closing a tab or WT may be fixed by this PR:
Validation Steps Performed
Before these changes I was able to consistently repro the issue in #2947. Now, I can no longer repro the issue.