Skip to content

Commit 05e336c

Browse files
committed
Fix a crash when TizenVsyncWaiter is destroyed.
* Don't have vblank_ecore_pipe as a member anymore * Does not consider abnormal situations. This means, this situation should never happen. * Refactor TizenVsyncWaiter Signed-off-by: Boram Bae <[email protected]>
1 parent 67f0349 commit 05e336c

File tree

3 files changed

+92
-110
lines changed

3 files changed

+92
-110
lines changed

shell/platform/tizen/tizen_embedder_engine.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,10 @@ bool TizenEmbedderEngine::RunEngine(
164164
return false;
165165
}
166166

167-
tizen_vsync_waiter_->AsyncWaitForRunEngineSuccess(flutter_engine);
167+
tizen_vsync_waiter_->SetFlutterEngine(flutter_engine);
168+
if (!tizen_vsync_waiter_->IsValid()) {
169+
LoggerW("TizenVsyncWaiter is not valid");
170+
}
168171

169172
std::unique_ptr<FlutterTextureRegistrar> textures =
170173
std::make_unique<FlutterTextureRegistrar>();
@@ -330,7 +333,9 @@ void TizenEmbedderEngine::OnFlutterPlatformMessage(
330333
void TizenEmbedderEngine::OnVsyncCallback(void* user_data, intptr_t baton) {
331334
TizenEmbedderEngine* tizen_embedder_engine =
332335
reinterpret_cast<TizenEmbedderEngine*>(user_data);
333-
tizen_embedder_engine->tizen_vsync_waiter_->AsyncWaitForVsync(baton);
336+
if (tizen_embedder_engine->tizen_vsync_waiter_->IsValid()) {
337+
tizen_embedder_engine->tizen_vsync_waiter_->AsyncWaitForVsync(baton);
338+
}
334339
}
335340

336341
// Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage.

shell/platform/tizen/tizen_vsync_waiter.cc

Lines changed: 73 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,85 @@
44

55
#include "tizen_vsync_waiter.h"
66

7+
#include <Ecore.h>
8+
79
#include "flutter/shell/platform/tizen/logger.h"
810

9-
TizenVsyncWaiter::TizenVsyncWaiter()
10-
: client_(NULL),
11-
output_(NULL),
12-
vblank_(NULL),
13-
flutter_engine_(nullptr),
14-
baton_(0),
15-
vblank_ecore_pipe_(NULL) {
16-
if (CreateTDMVblank()) {
17-
std::thread t(CreateVblankEventLoop, this);
18-
t.join();
19-
} else {
20-
LoggerE("CreateVsyncVaiter fail");
11+
static std::atomic<Ecore_Pipe*> g_vblank_ecore_pipe = nullptr;
12+
13+
static const int VBLANK_LOOP_REQUEST = 1;
14+
static const int VBLANK_LOOP_DEL_PIPE = 2;
15+
16+
static void SendVblankLoopRequest(int event_type) {
17+
if (ecore_pipe_write(g_vblank_ecore_pipe.load(), &event_type,
18+
sizeof(event_type)) == EINA_FALSE) {
19+
LoggerE("Failed to Send Reqeust [%s]", event_type == VBLANK_LOOP_REQUEST
20+
? "VBLANK_LOOP_REQUEST"
21+
: "VBLANK_LOOP_DEL_PIPE");
2122
}
2223
}
2324

24-
void TizenVsyncWaiter::CreateVblankEventLoop(void* data) {
25-
TizenVsyncWaiter* tizen_vsync_waiter =
26-
reinterpret_cast<TizenVsyncWaiter*>(data);
27-
if (!ecore_init()) {
28-
LoggerE("ERROR: Cannot init Ecore!");
25+
TizenVsyncWaiter::TizenVsyncWaiter() {
26+
if (!CreateTDMVblank()) {
27+
LoggerE("Failed to create TDM vblank");
2928
return;
3029
}
31-
tizen_vsync_waiter->vblank_ecore_pipe_ =
32-
ecore_pipe_add(VblankEventLoopCallback, tizen_vsync_waiter);
33-
LoggerD("ecore_init successful");
34-
ecore_main_loop_begin();
35-
ecore_shutdown();
36-
}
3730

38-
void TizenVsyncWaiter::VblankEventLoopCallback(void* data, void* buffer,
39-
unsigned int nbyte) {
40-
TizenVsyncWaiter* tizen_vsync_waiter =
41-
reinterpret_cast<TizenVsyncWaiter*>(data);
42-
int* event_type = reinterpret_cast<int*>(buffer);
43-
if ((*event_type) == VBLANK_LOOP_REQUEST) {
44-
tizen_vsync_waiter->AsyncWaitForVsyncCallback();
45-
} else if ((*event_type) == VBLANK_LOOP_DEL_PIPE) {
46-
tizen_vsync_waiter->DeleteVblankEventPipe();
31+
std::thread t(
32+
[this](void* data) {
33+
if (!ecore_init()) {
34+
LoggerE("Failed to init Ecore");
35+
return;
36+
}
37+
Ecore_Pipe* vblank_ecore_pipe = ecore_pipe_add(
38+
[](void* data, void* buffer, unsigned int nbyte) {
39+
TizenVsyncWaiter* tizen_vsync_waiter =
40+
reinterpret_cast<TizenVsyncWaiter*>(data);
41+
int event_type = *(reinterpret_cast<int*>(buffer));
42+
if (event_type == VBLANK_LOOP_REQUEST) {
43+
tizen_vsync_waiter->HandleVblankLoopRequest();
44+
} else if (event_type == VBLANK_LOOP_DEL_PIPE) {
45+
if (g_vblank_ecore_pipe.load()) {
46+
ecore_pipe_del(g_vblank_ecore_pipe);
47+
g_vblank_ecore_pipe = NULL;
48+
}
49+
ecore_main_loop_quit();
50+
}
51+
},
52+
this);
53+
54+
g_vblank_ecore_pipe.store(vblank_ecore_pipe);
55+
ecore_main_loop_begin();
56+
ecore_shutdown();
57+
},
58+
nullptr);
59+
t.join();
60+
61+
if (g_vblank_ecore_pipe.load() == nullptr) {
62+
LoggerE("Failed to create Ecore Pipe");
4763
}
4864
}
4965

50-
void TizenVsyncWaiter::AsyncWaitForVsyncCallback() {
51-
tdm_error ret;
52-
ret = tdm_client_vblank_wait(vblank_, 1, TdmClientVblankCallback, this);
53-
if (ret != TDM_ERROR_NONE) {
54-
LoggerE("ERROR, ret = %d", ret);
55-
return;
66+
TizenVsyncWaiter::~TizenVsyncWaiter() {
67+
if (g_vblank_ecore_pipe.load()) {
68+
SendVblankLoopRequest(VBLANK_LOOP_DEL_PIPE);
69+
}
70+
if (vblank_) {
71+
tdm_client_vblank_destroy(vblank_);
72+
}
73+
if (client_) {
74+
tdm_client_destroy(client_);
5675
}
57-
tdm_client_handle_events(client_);
5876
}
5977

60-
void TizenVsyncWaiter::DeleteVblankEventPipe() {
61-
if (vblank_ecore_pipe_) {
62-
ecore_pipe_del(vblank_ecore_pipe_);
63-
vblank_ecore_pipe_ = NULL;
64-
}
65-
ecore_main_loop_quit();
78+
void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) {
79+
baton_ = baton;
80+
SendVblankLoopRequest(VBLANK_LOOP_REQUEST);
81+
}
82+
83+
bool TizenVsyncWaiter::IsValid() {
84+
return g_vblank_ecore_pipe.load() && client_ && output_ && vblank_ &&
85+
flutter_engine_;
6686
}
6787

6888
bool TizenVsyncWaiter::CreateTDMVblank() {
@@ -94,57 +114,20 @@ void TizenVsyncWaiter::TdmClientVblankCallback(
94114
unsigned int tv_sec, unsigned int tv_usec, void* user_data) {
95115
TizenVsyncWaiter* tizen_vsync_waiter =
96116
reinterpret_cast<TizenVsyncWaiter*>(user_data);
97-
if (tizen_vsync_waiter == nullptr) {
98-
LoggerE("tizen_vsync_waiter is null");
99-
return;
100-
}
101-
if (tizen_vsync_waiter->flutter_engine_ == nullptr) {
102-
LoggerI("flutter engine creation is not completed");
103-
return;
104-
}
117+
105118
uint64_t frame_start_time_nanos = tv_sec * 1e9 + tv_usec * 1e3;
106119
uint64_t frame_target_time_nanos = 16.6 * 1e6 + frame_start_time_nanos;
107120
FlutterEngineOnVsync(tizen_vsync_waiter->flutter_engine_,
108121
tizen_vsync_waiter->baton_, frame_start_time_nanos,
109122
frame_target_time_nanos);
110123
}
111124

112-
bool TizenVsyncWaiter::AsyncWaitForVsync() {
113-
if (nullptr == flutter_engine_) {
114-
LoggerD("flutter_engine_ is null");
115-
return false;
116-
}
117-
if (vblank_ecore_pipe_) {
118-
int event_type = VBLANK_LOOP_REQUEST;
119-
ecore_pipe_write(vblank_ecore_pipe_, &event_type, sizeof(event_type));
120-
}
121-
return true;
122-
}
123-
124-
TizenVsyncWaiter::~TizenVsyncWaiter() {
125-
if (vblank_ecore_pipe_) {
126-
int event_type = VBLANK_LOOP_DEL_PIPE;
127-
ecore_pipe_write(vblank_ecore_pipe_, &event_type, sizeof(event_type));
128-
}
129-
if (vblank_) {
130-
tdm_client_vblank_destroy(vblank_);
131-
}
132-
if (client_) {
133-
tdm_client_destroy(client_);
134-
}
135-
}
136-
137-
void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) {
138-
baton_ = baton;
139-
AsyncWaitForVsync();
140-
}
141-
142-
void TizenVsyncWaiter::AsyncWaitForRunEngineSuccess(
143-
FLUTTER_API_SYMBOL(FlutterEngine) flutter_engine) {
144-
flutter_engine_ = flutter_engine;
145-
if (baton_ == 0) {
146-
LoggerD("baton_ == 0");
125+
void TizenVsyncWaiter::HandleVblankLoopRequest() {
126+
tdm_error ret;
127+
ret = tdm_client_vblank_wait(vblank_, 1, TdmClientVblankCallback, this);
128+
if (ret != TDM_ERROR_NONE) {
129+
LoggerE("ERROR, ret = %d", ret);
147130
return;
148131
}
149-
AsyncWaitForVsync();
150-
}
132+
tdm_client_handle_events(client_);
133+
}

shell/platform/tizen/tizen_vsync_waiter.h

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#ifndef EMBEDDER_TIZEN_VSYNC_WAITER_H_
66
#define EMBEDDER_TIZEN_VSYNC_WAITER_H_
77

8-
#include <Ecore.h>
98
#include <tdm_client.h>
109

1110
#include <thread>
@@ -16,30 +15,25 @@ class TizenVsyncWaiter {
1615
public:
1716
TizenVsyncWaiter();
1817
virtual ~TizenVsyncWaiter();
19-
bool CreateTDMVblank();
20-
bool AsyncWaitForVsync();
2118
void AsyncWaitForVsync(intptr_t baton);
22-
void AsyncWaitForRunEngineSuccess(FLUTTER_API_SYMBOL(FlutterEngine)
23-
flutter_engine);
19+
void SetFlutterEngine(FLUTTER_API_SYMBOL(FlutterEngine) flutter_engine) {
20+
flutter_engine_ = flutter_engine;
21+
}
22+
bool IsValid();
2423

2524
private:
26-
static const int VBLANK_LOOP_REQUEST = 1;
27-
static const int VBLANK_LOOP_DEL_PIPE = 2;
28-
void AsyncWaitForVsyncCallback();
29-
void DeleteVblankEventPipe();
30-
static void CreateVblankEventLoop(void* data);
25+
bool CreateTDMVblank();
26+
void HandleVblankLoopRequest();
3127
static void TdmClientVblankCallback(tdm_client_vblank* vblank,
3228
tdm_error error, unsigned int sequence,
3329
unsigned int tv_sec, unsigned int tv_usec,
3430
void* user_data);
35-
static void VblankEventLoopCallback(void* data, void* buffer,
36-
unsigned int nbyte);
37-
tdm_client* client_;
38-
tdm_client_output* output_;
39-
tdm_client_vblank* vblank_;
40-
FLUTTER_API_SYMBOL(FlutterEngine) flutter_engine_;
41-
intptr_t baton_;
42-
Ecore_Pipe* vblank_ecore_pipe_;
31+
32+
tdm_client* client_{nullptr};
33+
tdm_client_output* output_{nullptr};
34+
tdm_client_vblank* vblank_{nullptr};
35+
FLUTTER_API_SYMBOL(FlutterEngine) flutter_engine_{nullptr};
36+
intptr_t baton_{0};
4337
};
4438

4539
#endif // EMBEDDER_TIZEN_VSYNC_WAITER_H_

0 commit comments

Comments
 (0)