Index: ui/accelerated_widget_mac/display_link_mac.cc |
diff --git a/ui/accelerated_widget_mac/display_link_mac.cc b/ui/accelerated_widget_mac/display_link_mac.cc |
index d9cc46876f9f53a8aea2e04a668421efe6f5ffd5..72470f64b1ed0c35045310ceb4097952667392e4 100644 |
--- a/ui/accelerated_widget_mac/display_link_mac.cc |
+++ b/ui/accelerated_widget_mac/display_link_mac.cc |
@@ -25,6 +25,20 @@ struct ScopedTypeRefTraits<CVDisplayLinkRef> { |
} // namespace base |
+namespace { |
+ |
+// Empty callback set during tear down. |
+CVReturn VoidDisplayLinkCallback(CVDisplayLinkRef display_link, |
+ const CVTimeStamp* now, |
+ const CVTimeStamp* output_time, |
+ CVOptionFlags flags_in, |
+ CVOptionFlags* flags_out, |
+ void* context) { |
+ return kCVReturnSuccess; |
+} |
+ |
+} // namespace |
+ |
namespace ui { |
// static |
@@ -86,6 +100,14 @@ DisplayLinkMac::DisplayLinkMac( |
DisplayLinkMac::~DisplayLinkMac() { |
StopDisplayLink(); |
+ // Usually |display_link_| holds the last reference to CVDisplayLinkRef, but |
+ // that's not guaranteed, so it might not free all resources after the |
+ // destructor completes. Ensure the callback is cleared out regardless to |
+ // avoid possible crashes (see http://crbug.com/564780). |
+ CVReturn ret = CVDisplayLinkSetOutputCallback( |
+ display_link_, VoidDisplayLinkCallback, nullptr); |
+ DCHECK_EQ(kCGErrorSuccess, ret); |
+ |
DisplayMap::iterator found = display_map_.Get().find(display_id_); |
DCHECK(found != display_map_.Get().end()); |
DCHECK(found->second == this); |