Skip to content

Commit 810f072

Browse files
author
Chih-Yi Leu
committed
Bug 1221730 - Postpone singleton release in GamepadPlatformService::MaybeShutdown. r=baku
--HG-- extra : rebase_source : 4031bb8e791fa1c915261f3b2eaece28ebadb283
1 parent 8733310 commit 810f072

File tree

9 files changed

+101
-51
lines changed

9 files changed

+101
-51
lines changed

dom/gamepad/GamepadMonitoring.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ void
1717
MaybeStopGamepadMonitoring()
1818
{
1919
AssertIsOnBackgroundThread();
20-
GamepadPlatformService* service =
20+
RefPtr<GamepadPlatformService> service =
2121
GamepadPlatformService::GetParentService();
2222
MOZ_ASSERT(service);
2323
if(service->HasGamepadListeners()) {

dom/gamepad/GamepadPlatformService.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace {
2424

2525
// This is the singleton instance of GamepadPlatformService, can be called
2626
// by both background and monitor thread.
27-
StaticAutoPtr<GamepadPlatformService> gGamepadPlatformServiceSingleton;
27+
StaticRefPtr<GamepadPlatformService> gGamepadPlatformServiceSingleton;
2828

2929
} //namepsace
3030

@@ -39,15 +39,21 @@ GamepadPlatformService::~GamepadPlatformService()
3939
}
4040

4141
// static
42-
GamepadPlatformService*
42+
already_AddRefed<GamepadPlatformService>
4343
GamepadPlatformService::GetParentService()
4444
{
4545
//GamepadPlatformService can only be accessed in parent process
4646
MOZ_ASSERT(XRE_IsParentProcess());
47-
if(!gGamepadPlatformServiceSingleton) {
48-
gGamepadPlatformServiceSingleton = new GamepadPlatformService();
47+
if (!gGamepadPlatformServiceSingleton) {
48+
// Only Background Thread can create new GamepadPlatformService instance.
49+
if (IsOnBackgroundThread()) {
50+
gGamepadPlatformServiceSingleton = new GamepadPlatformService();
51+
} else {
52+
return nullptr;
53+
}
4954
}
50-
return gGamepadPlatformServiceSingleton;
55+
RefPtr<GamepadPlatformService> service(gGamepadPlatformServiceSingleton);
56+
return service.forget();
5157
}
5258

5359
template<class T>
@@ -195,13 +201,21 @@ GamepadPlatformService::MaybeShutdown()
195201
// an IPDL channel is going to be destroyed
196202
AssertIsOnBackgroundThread();
197203

204+
// We have to release gGamepadPlatformServiceSingleton ouside
205+
// the mutex as well as making upcoming GetParentService() call
206+
// recreate new singleton, so we use this RefPtr to temporarily
207+
// hold the reference, postponing the release process until this
208+
// method ends.
209+
RefPtr<GamepadPlatformService> kungFuDeathGrip;
210+
198211
bool isChannelParentEmpty;
199212
{
200213
MutexAutoLock autoLock(mMutex);
201214
isChannelParentEmpty = mChannelParents.IsEmpty();
202-
}
203-
if(isChannelParentEmpty) {
204-
gGamepadPlatformServiceSingleton = nullptr;
215+
if(isChannelParentEmpty) {
216+
kungFuDeathGrip = gGamepadPlatformServiceSingleton;
217+
gGamepadPlatformServiceSingleton = nullptr;
218+
}
205219
}
206220
}
207221

dom/gamepad/GamepadPlatformService.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ class GamepadEventChannelParent;
3131
// is in charge of processing gamepad hardware events from OS
3232
class GamepadPlatformService final
3333
{
34+
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GamepadPlatformService)
3435
public:
35-
~GamepadPlatformService();
3636
//Get the singleton service
37-
static GamepadPlatformService* GetParentService();
37+
static already_AddRefed<GamepadPlatformService> GetParentService();
3838

3939
// Add a gamepad to the list of known gamepads, and return its index.
4040
uint32_t AddGamepad(const char* aID, GamepadMappingType aMapping,
@@ -72,6 +72,7 @@ class GamepadPlatformService final
7272

7373
private:
7474
GamepadPlatformService();
75+
~GamepadPlatformService();
7576
template<class T> void NotifyGamepadChange(const T& aInfo);
7677
void Cleanup();
7778

dom/gamepad/cocoa/CocoaGamepad.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ class DarwinGamepadServiceStartupRunnable final : public Runnable
247247
void
248248
DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device)
249249
{
250+
RefPtr<GamepadPlatformService> service =
251+
GamepadPlatformService::GetParentService();
252+
if (!service) {
253+
return;
254+
}
255+
250256
size_t slot = size_t(-1);
251257
for (size_t i = 0; i < mGamepads.size(); i++) {
252258
if (mGamepads[i] == device)
@@ -276,9 +282,6 @@ DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device)
276282
sizeof(product_name), kCFStringEncodingASCII);
277283
char buffer[256];
278284
sprintf(buffer, "%x-%x-%s", vendorId, productId, product_name);
279-
GamepadPlatformService* service =
280-
GamepadPlatformService::GetParentService();
281-
MOZ_ASSERT(service);
282285
uint32_t index = service->AddGamepad(buffer,
283286
mozilla::dom::GamepadMappingType::_empty,
284287
(int)mGamepads[slot].numButtons(),
@@ -289,9 +292,11 @@ DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device)
289292
void
290293
DarwinGamepadService::DeviceRemoved(IOHIDDeviceRef device)
291294
{
292-
GamepadPlatformService* service =
295+
RefPtr<GamepadPlatformService> service =
293296
GamepadPlatformService::GetParentService();
294-
MOZ_ASSERT(service);
297+
if (!service) {
298+
return;
299+
}
295300
for (size_t i = 0; i < mGamepads.size(); i++) {
296301
if (mGamepads[i] == device) {
297302
service->RemoveGamepad(mGamepads[i].mSuperIndex);
@@ -343,6 +348,12 @@ UnpackDpad(int dpad_value, int min, int max, dpad_buttons& buttons)
343348
void
344349
DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
345350
{
351+
RefPtr<GamepadPlatformService> service =
352+
GamepadPlatformService::GetParentService();
353+
if (!service) {
354+
return;
355+
}
356+
346357
uint32_t value_length = IOHIDValueGetLength(value);
347358
if (value_length > 4) {
348359
// Workaround for bizarre issue with PS3 controllers that try to return
@@ -351,9 +362,7 @@ DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
351362
}
352363
IOHIDElementRef element = IOHIDValueGetElement(value);
353364
IOHIDDeviceRef device = IOHIDElementGetDevice(element);
354-
GamepadPlatformService* service =
355-
GamepadPlatformService::GetParentService();
356-
MOZ_ASSERT(service);
365+
357366
for (unsigned i = 0; i < mGamepads.size(); i++) {
358367
Gamepad &gamepad = mGamepads[i];
359368
if (gamepad == device) {

dom/gamepad/ipc/GamepadEventChannelParent.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class SendGamepadUpdateRunnable final : public Runnable
4242
GamepadEventChannelParent::GamepadEventChannelParent()
4343
: mHasGamepadListener(false)
4444
{
45-
GamepadPlatformService* service =
45+
RefPtr<GamepadPlatformService> service =
4646
GamepadPlatformService::GetParentService();
4747
MOZ_ASSERT(service);
4848
service->AddChannelParent(this);
@@ -65,7 +65,7 @@ GamepadEventChannelParent::RecvGamepadListenerRemoved()
6565
AssertIsOnBackgroundThread();
6666
MOZ_ASSERT(mHasGamepadListener);
6767
mHasGamepadListener = false;
68-
GamepadPlatformService* service =
68+
RefPtr<GamepadPlatformService> service =
6969
GamepadPlatformService::GetParentService();
7070
MOZ_ASSERT(service);
7171
service->RemoveChannelParent(this);
@@ -82,7 +82,7 @@ GamepadEventChannelParent::ActorDestroy(ActorDestroyReason aWhy)
8282
// not receive RecvGamepadListenerRemoved in that case
8383
if (mHasGamepadListener) {
8484
mHasGamepadListener = false;
85-
GamepadPlatformService* service =
85+
RefPtr<GamepadPlatformService> service =
8686
GamepadPlatformService::GetParentService();
8787
MOZ_ASSERT(service);
8888
service->RemoveChannelParent(this);

dom/gamepad/ipc/GamepadTestChannelParent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ GamepadTestChannelParent::RecvGamepadTestEvent(const uint32_t& aID,
1515
const GamepadChangeEvent& aEvent)
1616
{
1717
mozilla::ipc::AssertIsOnBackgroundThread();
18-
GamepadPlatformService* service =
18+
RefPtr<GamepadPlatformService> service =
1919
GamepadPlatformService::GetParentService();
2020
MOZ_ASSERT(service);
2121
if (aEvent.type() == GamepadChangeEvent::TGamepadAdded) {

dom/gamepad/linux/LinuxGamepad.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ LinuxGamepadService* gService = nullptr;
8686
void
8787
LinuxGamepadService::AddDevice(struct udev_device* dev)
8888
{
89+
RefPtr<GamepadPlatformService> service =
90+
GamepadPlatformService::GetParentService();
91+
if (!service) {
92+
return;
93+
}
94+
8995
const char* devpath = mUdev.udev_device_get_devnode(dev);
9096
if (!devpath) {
9197
return;
@@ -134,9 +140,6 @@ LinuxGamepadService::AddDevice(struct udev_device* dev)
134140
name);
135141

136142
char numAxes = 0, numButtons = 0;
137-
GamepadPlatformService* service =
138-
GamepadPlatformService::GetParentService();
139-
MOZ_ASSERT(service);
140143
ioctl(fd, JSIOCGAXES, &numAxes);
141144
gamepad.numAxes = numAxes;
142145
ioctl(fd, JSIOCGBUTTONS, &numButtons);
@@ -160,13 +163,17 @@ LinuxGamepadService::AddDevice(struct udev_device* dev)
160163
void
161164
LinuxGamepadService::RemoveDevice(struct udev_device* dev)
162165
{
166+
RefPtr<GamepadPlatformService> service =
167+
GamepadPlatformService::GetParentService();
168+
if (!service) {
169+
return;
170+
}
171+
163172
const char* devpath = mUdev.udev_device_get_devnode(dev);
164173
if (!devpath) {
165174
return;
166175
}
167-
GamepadPlatformService* service =
168-
GamepadPlatformService::GetParentService();
169-
MOZ_ASSERT(service);
176+
170177
for (unsigned int i = 0; i < mGamepads.Length(); i++) {
171178
if (strcmp(mGamepads[i].devpath, devpath) == 0) {
172179
g_source_remove(mGamepads[i].source_id);
@@ -300,10 +307,12 @@ LinuxGamepadService::OnGamepadData(GIOChannel* source,
300307
GIOCondition condition,
301308
gpointer data)
302309
{
303-
int index = GPOINTER_TO_INT(data);
304-
GamepadPlatformService* service =
310+
RefPtr<GamepadPlatformService> service =
305311
GamepadPlatformService::GetParentService();
306-
MOZ_ASSERT(service);
312+
if (!service) {
313+
return TRUE;
314+
}
315+
int index = GPOINTER_TO_INT(data);
307316
//TODO: remove gamepad?
308317
if (condition & G_IO_ERR || condition & G_IO_HUP)
309318
return FALSE;

dom/gamepad/windows/WindowsGamepad.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,12 @@ WindowsGamepadService::ScanForXInputDevices()
431431
MOZ_ASSERT(mXInput, "XInput should be present!");
432432

433433
bool found = false;
434+
RefPtr<GamepadPlatformService> service =
435+
GamepadPlatformService::GetParentService();
436+
if (!service) {
437+
return found;
438+
}
439+
434440
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
435441
XINPUT_STATE state = {};
436442
if (mXInput.mXInputGetState(i, &state) != ERROR_SUCCESS) {
@@ -443,9 +449,6 @@ WindowsGamepadService::ScanForXInputDevices()
443449
}
444450

445451
// Not already present, add it.
446-
GamepadPlatformService* service =
447-
GamepadPlatformService::GetParentService();
448-
MOZ_ASSERT(service);
449452
Gamepad gamepad = {};
450453
gamepad.type = kXInputGamepad;
451454
gamepad.present = true;
@@ -466,6 +469,12 @@ WindowsGamepadService::ScanForXInputDevices()
466469
void
467470
WindowsGamepadService::ScanForDevices()
468471
{
472+
RefPtr<GamepadPlatformService> service =
473+
GamepadPlatformService::GetParentService();
474+
if (!service) {
475+
return;
476+
}
477+
469478
for (int i = mGamepads.Length() - 1; i >= 0; i--) {
470479
mGamepads[i].present = false;
471480
}
@@ -486,9 +495,6 @@ WindowsGamepadService::ScanForDevices()
486495
}
487496

488497
// Look for devices that are no longer present and remove them.
489-
GamepadPlatformService* service =
490-
GamepadPlatformService::GetParentService();
491-
MOZ_ASSERT(service);
492498
for (int i = mGamepads.Length() - 1; i >= 0; i--) {
493499
if (!mGamepads[i].present) {
494500
service->RemoveGamepad(mGamepads[i].id);
@@ -516,9 +522,11 @@ WindowsGamepadService::PollXInput()
516522

517523
void WindowsGamepadService::CheckXInputChanges(Gamepad& gamepad,
518524
XINPUT_STATE& state) {
519-
GamepadPlatformService* service =
525+
RefPtr<GamepadPlatformService> service =
520526
GamepadPlatformService::GetParentService();
521-
MOZ_ASSERT(service);
527+
if (!service) {
528+
return;
529+
}
522530
// Handle digital buttons first
523531
for (size_t b = 0; b < kNumMappings; b++) {
524532
if (state.Gamepad.wButtons & kXIButtonMap[b].button &&
@@ -586,6 +594,12 @@ class HidValueComparator {
586594
bool
587595
WindowsGamepadService::GetRawGamepad(HANDLE handle)
588596
{
597+
RefPtr<GamepadPlatformService> service =
598+
GamepadPlatformService::GetParentService();
599+
if (!service) {
600+
return true;
601+
}
602+
589603
if (!mHID) {
590604
return false;
591605
}
@@ -722,10 +736,6 @@ WindowsGamepadService::GetRawGamepad(HANDLE handle)
722736
gamepad.type = kRawInputGamepad;
723737
gamepad.handle = handle;
724738
gamepad.present = true;
725-
726-
GamepadPlatformService* service =
727-
GamepadPlatformService::GetParentService();
728-
MOZ_ASSERT(service);
729739
gamepad.id = service->AddGamepad(gamepad_id,
730740
GamepadMappingType::_empty,
731741
gamepad.numButtons,
@@ -741,6 +751,12 @@ WindowsGamepadService::HandleRawInput(HRAWINPUT handle)
741751
return false;
742752
}
743753

754+
RefPtr<GamepadPlatformService> service =
755+
GamepadPlatformService::GetParentService();
756+
if (service) {
757+
return true;
758+
}
759+
744760
// First, get data from the handle
745761
UINT size;
746762
GetRawInputData(handle, RID_INPUT, nullptr, &size, sizeof(RAWINPUTHEADER));
@@ -773,9 +789,6 @@ WindowsGamepadService::HandleRawInput(HRAWINPUT handle)
773789
reinterpret_cast<PHIDP_PREPARSED_DATA>(parsedbytes.Elements());
774790

775791
// Get all the pressed buttons.
776-
GamepadPlatformService* service =
777-
GamepadPlatformService::GetParentService();
778-
MOZ_ASSERT(service);
779792
nsTArray<USAGE> usages(gamepad->numButtons);
780793
usages.SetLength(gamepad->numButtons);
781794
ULONG usageLength = gamepad->numButtons;

widget/android/nsAppShell.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,11 @@ nsAppShell::LegacyGeckoEvent::Run()
934934

935935
case AndroidGeckoEvent::GAMEPAD_ADDREMOVE: {
936936
#ifdef MOZ_GAMEPAD
937-
GamepadPlatformService* service;
937+
RefPtr<GamepadPlatformService> service;
938938
service = GamepadPlatformService::GetParentService();
939-
MOZ_ASSERT(service);
939+
if (!service) {
940+
break;
941+
}
940942
if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_ADDED) {
941943
int svc_id = service->AddGamepad("android",
942944
dom::GamepadMappingType::Standard,
@@ -954,9 +956,11 @@ nsAppShell::LegacyGeckoEvent::Run()
954956
case AndroidGeckoEvent::GAMEPAD_DATA: {
955957
#ifdef MOZ_GAMEPAD
956958
int id = curEvent->ID();
957-
GamepadPlatformService* service;
959+
RefPtr<GamepadPlatformService> service;
958960
service = GamepadPlatformService::GetParentService();
959-
MOZ_ASSERT(service);
961+
if (!service) {
962+
break;
963+
}
960964
if (curEvent->Action() == AndroidGeckoEvent::ACTION_GAMEPAD_BUTTON) {
961965
service->NewButtonEvent(id, curEvent->GamepadButton(),
962966
curEvent->GamepadButtonPressed(),

0 commit comments

Comments
 (0)