forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid calling Dart timeline APIs during Dart_Cleanup (flutter#24007)
The Dart timeline is not thread safe if an engine thread that is not controlled by Dart calls Dart_TimelineEvent while another thread is calling Dart_Cleanup. Fixes flutter/flutter#74134
- Loading branch information
1 parent
d6b8eba
commit df4e79d
Showing
8 changed files
with
127 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "flutter/runtime/dart_vm_initializer.h" | ||
|
||
#include <atomic> | ||
|
||
#include "flutter/fml/logging.h" | ||
#include "flutter/fml/synchronization/shared_mutex.h" | ||
#include "flutter/fml/trace_event.h" | ||
|
||
// Tracks whether Dart has been initialized and if it is safe to call Dart | ||
// APIs. | ||
static std::atomic<bool> gDartInitialized; | ||
|
||
void DartVMInitializer::Initialize(Dart_InitializeParams* params) { | ||
FML_DCHECK(!gDartInitialized); | ||
|
||
char* error = Dart_Initialize(params); | ||
if (error) { | ||
FML_LOG(FATAL) << "Error while initializing the Dart VM: " << error; | ||
::free(error); | ||
} else { | ||
gDartInitialized = true; | ||
} | ||
|
||
fml::tracing::TraceSetTimelineEventHandler(LogDartTimelineEvent); | ||
} | ||
|
||
void DartVMInitializer::Cleanup() { | ||
FML_DCHECK(gDartInitialized); | ||
|
||
// Dart_TimelineEvent is unsafe during a concurrent call to Dart_Cleanup | ||
// because Dart_Cleanup will destroy the timeline recorder. Clear the | ||
// initialized flag so that future calls to LogDartTimelineEvent will not | ||
// call Dart_TimelineEvent. | ||
// | ||
// Note that this is inherently racy. If a thread sees that gDartInitialized | ||
// is set and proceeds to call Dart_TimelineEvent shortly before another | ||
// thread calls Dart_Cleanup, then the Dart_TimelineEvent call may crash | ||
// if Dart_Cleanup deletes the timeline before Dart_TimelineEvent completes. | ||
// In practice this is unlikely because Dart_Cleanup does significant other | ||
// work before deleting the timeline. | ||
// | ||
// The engine can not safely guard Dart_Cleanup and LogDartTimelineEvent with | ||
// a lock due to the risk of deadlocks. Dart_Cleanup waits for various | ||
// Dart-owned threads to shut down. If one of those threads invokes an engine | ||
// callback that calls LogDartTimelineEvent while the Dart_Cleanup thread owns | ||
// the lock, then Dart_Cleanup would deadlock. | ||
gDartInitialized = false; | ||
|
||
char* error = Dart_Cleanup(); | ||
if (error) { | ||
FML_LOG(FATAL) << "Error while cleaning up the Dart VM: " << error; | ||
::free(error); | ||
} | ||
} | ||
|
||
void DartVMInitializer::LogDartTimelineEvent(const char* label, | ||
int64_t timestamp0, | ||
int64_t timestamp1_or_async_id, | ||
Dart_Timeline_Event_Type type, | ||
intptr_t argument_count, | ||
const char** argument_names, | ||
const char** argument_values) { | ||
if (gDartInitialized) { | ||
Dart_TimelineEvent(label, timestamp0, timestamp1_or_async_id, type, | ||
argument_count, argument_names, argument_values); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef FLUTTER_RUNTIME_DART_VM_INITIALIZER_H_ | ||
#define FLUTTER_RUNTIME_DART_VM_INITIALIZER_H_ | ||
|
||
#include "third_party/dart/runtime/include/dart_api.h" | ||
#include "third_party/dart/runtime/include/dart_tools_api.h" | ||
|
||
class DartVMInitializer { | ||
public: | ||
static void Initialize(Dart_InitializeParams* params); | ||
static void Cleanup(); | ||
|
||
private: | ||
static void LogDartTimelineEvent(const char* label, | ||
int64_t timestamp0, | ||
int64_t timestamp1_or_async_id, | ||
Dart_Timeline_Event_Type type, | ||
intptr_t argument_count, | ||
const char** argument_names, | ||
const char** argument_values); | ||
}; | ||
|
||
#endif // FLUTTER_RUNTIME_DART_VM_INITIALIZER_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters