Сценарий Python завершается SIGKILL, а не выбрасывает MemoryError

Обновить снова

Я пытался создать какой-то простой способ воспроизвести это, но безуспешно.

До сих пор я пробовал различные простые выделения и манипуляции с массивами, но все они генерируют MemoryError, а не просто сбой SIGKILL.

Например:

x =np.asarray(range(999999999))

или же:

x = np.empty([100,100,100,100,7])

просто киньте MemoryErrors как надо.

Я надеюсь иметь простой способ воссоздать это в какой-то момент.

Конец обновления

У меня есть скрипт на Python, который запускает Numpy/ Scipy и некоторые пользовательские расширения Си.

На моем Ubuntu 14.04 под Virtual Box, он работает до завершения просто отлично.

На микроэкземпляре Amazon EC2 T2 он завершается (через некоторое время) выводом:

убитый

Работая под отладчиком python, сигнал не перехватывается, и отладчик также завершается.

Работая под натяжкой, я получаю:

munmap(0x7fa5b7fa6000, 67112960)        = 0
mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5b7fa6000    
mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5affa4000    
mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5abfa3000    
mmap(NULL, 67637248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5a7f22000    
mmap(NULL, 67637248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5a3ea1000    
mmap(NULL, 67637248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa59fe20000    
gettimeofday({1406518336, 306209}, NULL) = 0    
gettimeofday({1406518336, 580022}, NULL) = 0    
+++ killed by SIGKILL +++

работая под GDB, пытаясь поймать "SIGKILL", я получаю:

[Thread 0x7fffe7148700 (LWP 28022) exited]

Program terminated with signal SIGKILL, Killed.
The program no longer exists.
(gdb) where
No stack.

запустив модуль трассировки python (python -m trace --trace), я получаю:

defmatrix.py(292):         if (isinstance(obj, matrix) and obj._getitem): return
defmatrix.py(293):         ndim = self.ndim
defmatrix.py(294):         if (ndim == 2):
defmatrix.py(295):             return
defmatrix.py(336):         return out
 --- modulename: linalg, funcname: norm
linalg.py(2052):     x = asarray(x)
 --- modulename: numeric, funcname: asarray
numeric.py(460):     return array(a, dtype, copy=False, order=order)

Я не могу думать ни о чем другом в данный момент, чтобы понять, что происходит.

Я подозреваю, что, возможно, не хватает памяти (это экземпляр AWS Micro), но я не могу понять, как это подтвердить или опровергнуть.

Есть ли другой инструмент, который я мог бы использовать, чтобы помочь точно определить, где именно останавливается программа? (или я использую один из вышеперечисленных инструментов неправильно для этой проблемы?)

Обновить

Микроэкземпляр Amazon EC2 T2 не имеет пространства подкачки, определенного по умолчанию, поэтому я добавил файл подкачки объемом 4 ГБ и смог запустить программу до конца.

Тем не менее, я по-прежнему очень заинтересован в том, чтобы запустить программу так, чтобы она заканчивалась каким-то сообщением, немного ближе к "Недостаточно памяти", а не "Убито".

Если у кого-то есть какие-либо предложения, они будут оценены.

1 ответ

Решение

Похоже, вы столкнулись с ужасным убийцей Linux OOM. Когда в системе полностью не хватает памяти и ядру абсолютно необходимо выделить память, это убивает процесс, а не приводит к сбою всей системы.

Посмотрите в системном журнале подтверждение этого. Строка, похожая на:

kernel: [884145.344240] mysqld invoked oom-killer:

последовал спустя некоторое время с:

kernel: [884145.344399] Out of memory: Kill process 3318

Должен присутствовать (в этом примере он упоминает MySQL конкретно)

Вы можете добавить эти строки в свой /etc/sysctl.conf файл для эффективного отключения убийцы OOM:

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

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

настройка overcommit_memory означает, что Linux не будет чрезмерно фиксировать память, то есть выделение памяти не будет выполнено, если для них не будет достаточно памяти. Посмотрите этот ответ для деталей о том, как overcommit_ratio имеет: /questions/21030573/ispolzovanie-base-v-imeni-klassa/21030598#21030598

Другие вопросы по тегам