Mandelbug, связанный с WakeLock: всегда ли WakeLock.acquire() завершается успешно?

Проблема

Я занимаюсь разработкой для Android уже довольно давно. Одна из разработанных мной программ активно использует WakeLocks. . Обычно все отлично (часто днями или неделями, требование программы), но очень редко я замечаю странное поведение в этом коде:

acquireWakeLock(wakeLockManager)

    // Preconditions
    assertFalse("Wake lock already acquired.", hasWakeLock());
    assertNotNull("Wake lock manager not provided.", wakeLockManager);

    // Acquire a wake lock.
    wakeLock = wakeLockManager.newPartialWakeLock(DEBUG_TAG);
    wakeLock.acquire();

    // Postconditions
    assertTrue("Wake Lock should be held!", hasWakeLock());

Где hasWakeLock() просто возвращает результат (wakeLock != null && wakeLock.isHeld()), а wakeLockManager.newPartialWakeLock(DEBUG_TAG) инкапсулирует стандартный код «получить PowerManager, а затем вернуть блокировку пробуждения». В целях тестирования операторы assert являются методами JUnit assert, поэтому я думаю, что мы можем предположить, что они верны.

Проблема с кодом заключается в следующем: последнее утверждение — assertTrue(hasWakeLock()) — кажется, терпит неудачу каждые несколько недель с очень небольшим объяснением. Это означает, что у меня есть три возможных проблемы: (1) блокировка пробуждения вообще никогда не извлекается из PowerManager (2) что у меня есть проблема параллелизма, которая в редких случаях вступает в силу непосредственно перед постусловием, но после вызова acquire(), или что (3) acquire() иногда неисправен.

Исследование проблемы

Как указано выше, у меня есть три потенциальных проблемы, которые могут возникнуть, которые я расследую/расследовал:

Гипотеза 1: блокировка пробуждения не возвращена:

Если бы это было так, я бы увидел исключение нулевого указателя. Этого не может быть.

Гипотеза 2. У меня проблема с параллелизмом:

Только что проведенная официальная проверка всех мест, участвующих в приобретении и выпуске wakeLock убедительно заставляет меня поверить, что это не так. В случае, если мое доказательство ошибочно, у меня может возникнуть проблема параллелизма, но тогда она действительно коварна и ее трудно найти.

Гипотеза 3. WakeLock.acquire() неисправен и несмотря на то, что говорится в документации, иногда может не получиться блокировка:

Мне не нравится эта гипотеза, потому что со всеми пользователями Android наш кто-то помимо меня, должно быть, уже заметил это, и почти всегда это код разработчика, а не код библиотеки или ОС, который ошибочен. С другой стороны, произошли более странные вещи, и это может быть настоящей ошибкой Android, хотя и редко проявляющейся. Если эта гипотеза верна, то функцияAcquire() просто не получает блокировку пробуждения, и это объясняет поведение, которое я наблюдаю.

Итак, StackOverflow, что может быть причиной этой проблемы? Как вы думаете, что не так? Я упускаю что-то очевидное, или это может быть настоящая проблема с блокировкой пробуждения Android?


person Dylan Knowles    schedule 25.08.2011    source источник
comment
Вы видите эту ошибку на устройствах от разных производителей? Или, может быть, вам удалось воспроизвести это и на эмуляторе?   -  person inazaruk    schedule 25.08.2011
comment
Только на устройстве Google IO. Я использую на нем пользовательскую версию Android 2.1; пользовательская версия только изменяет код Bluetooth.   -  person Dylan Knowles    schedule 25.08.2011
comment
Если эта ошибка настолько редка, как вы ее описываете, моей первой ставкой было бы воспроизвести ее на устройствах другого производителя или на том же устройстве с Android 2.2.   -  person inazaruk    schedule 25.08.2011
comment
Если бы у меня был другой тип устройства, я бы так и сделал. К сожалению, я также не могу использовать эмулятор, так как эта программа сильно зависит от данных датчиков.   -  person Dylan Knowles    schedule 25.08.2011
comment
Как насчет получения и освобождения WakeLock много раз в цикле. Простое простое приложение со службой и фоновым потоком, который делает это. Возможно, вы сможете воспроизвести эту проблему быстрее, чем раз в неделю. Если это так, я был бы рад попробовать приложение на одном из моих устройств.   -  person inazaruk    schedule 25.08.2011
comment
Это интересная мысль, но, к сожалению, возникли другие приоритеты. Я буду иметь это в виду и попробую здесь, если мои коллеги и/или я тем временем приобрету новое оборудование.   -  person Dylan Knowles    schedule 29.08.2011


Ответы (1)


Казалось бы, это действительно проблема параллелизма. Я упустил из виду тот факт, что соответствующий метод может быть вызван из несинхронизированного местоположения в отдельном потоке — очевидная проблема в многопоточной среде!

person Dylan Knowles    schedule 21.01.2012