"Ошибка WindowsE: доступ запрещен" при вызове Process.terminate

Я применяю таймаут для блока кода, используя multiprocessing модуль. Похоже, что при входных данных определенного размера возникает следующая ошибка:

WindowsError: [Error 5] Access is denied

Я могу повторить эту ошибку с помощью следующего кода. Обратите внимание, что код завершается с "467,912,040", но не с "517,912,040".

import multiprocessing, Queue

def wrapper(queue, lst):
    lst.append(1)
    queue.put(lst)
    queue.close()

def timeout(timeout, lst):
    q = multiprocessing.Queue(1)
    proc = multiprocessing.Process(target=wrapper, args=(q, lst))
    proc.start()
    try:
        result = q.get(True, timeout)
    except Queue.Empty:
        return None
    finally:
        proc.terminate()
    return result

if __name__ == "__main__":
    # lst = [0]*417912040 # this works fine
    # lst = [0]*467912040 # this works fine
    lst = [0] * 517912040 # this does not
    print "List length:",len(lst)
    timeout(60*30, lst)

Вывод (включая ошибку):

List length: 517912040

Traceback (most recent call last):
  File ".\multiprocessing_error.py", line 29, in <module>
    print "List length:",len(lst)
  File ".\multiprocessing_error.py", line 21, in timeout
    proc.terminate()
  File "C:\Python27\lib\multiprocessing\process.py", line 137, in terminate
    self._popen.terminate()
  File "C:\Python27\lib\multiprocessing\forking.py", line 306, in terminate
    _subprocess.TerminateProcess(int(self._handle), TERMINATE)
WindowsError: [Error 5] Access is denied

Разрешено ли мне прекратить процесс определенного размера?

Я использую Python 2.7 на Windows 7 (64bit).

1 ответ

Решение

Хотя я все еще не уверен относительно точной причины проблемы, у меня есть некоторые дополнительные наблюдения, а также обходной путь.

Обходной путь.

Добавление try-except блок в окончательном предложении.

finally:
    try:
        proc.terminate()
    except WindowsError:
        pass

Похоже, что это также решение проблемы, связанной с (?), Размещенной здесь на GitHub (возможно, вам придется немного прокрутить вниз).

Наблюдения.

  1. Эта ошибка зависит от размера объекта, передаваемого в процесс / очередь, но не связана с выполнением самого процесса. В OP процесс завершается до истечения времени ожидания.
  2. proc.is_alive возвращается True до и после исполнения proc.terminate() (который затем выбрасывает WindowsError). Через секунду или две, proc.is_alive() возвращается False и второй звонок proc.terminate() преуспевает.
  3. Заставляя основной поток спать time.sleep(1) в finally Блок также предотвращает выброс WindowsError. Спасибо, комментарий @tdelaney в ОП.
  4. Я думаю, что proc находится в процессе освобождения памяти (?, или что-то сопоставимое) во время уничтожения ОС (после завершения выполнения) при обращении к proc.terminate() пытается убить его снова.
Другие вопросы по тегам