Підпроцес Python. Відкрийте "OSError: [Errno 12] Неможливо виділити пам'ять"


114

Примітка. Спочатку це запитання було задано тут, але термін щедрості минув, хоча прийнятної відповіді насправді не знайдено. Я повторно задаю це питання, включаючи всі деталі, наведені в оригінальному запитанні.

Сценарій python виконує набір функцій класу кожні 60 секунд за допомогою модуля планування :

# sc is a sched.scheduler instance
sc.enter(60, 1, self.doChecks, (sc, False))

Сценарій працює як демонстований процес, використовуючи тут код .

Ряд методів класу, які викликаються як частина doChecks, використовують модуль підпроцеси для виклику системних функцій для отримання системної статистики:

ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]

Це спрацьовує за певний проміжок часу, перш ніж весь сценарій завершиться збоєм із наступною помилкою:

File "/home/admin/sd-agent/checks.py", line 436, in getProcesses
File "/usr/lib/python2.4/subprocess.py", line 533, in __init__
File "/usr/lib/python2.4/subprocess.py", line 835, in _get_handles
OSError: [Errno 12] Cannot allocate memory

Вихід free -m на сервер після того, як сценарій вийшов з ладу, це:

$ free -m
                  total       used       free     shared     buffers    cached
Mem:                894        345        549          0          0          0
-/+ buffers/cache:  345        549
Swap:                 0          0          0

На сервері працює CentOS 5.3. Я не в змозі відтворити власні вікна CentOS, ані інший користувач, який повідомив про ту ж проблему.

Я спробував налагодити це, як було запропоновано в оригінальному запитанні:

  1. Реєстрація виходу free -m до і після виклику Popen. Немає суттєвих змін у використанні пам’яті, тобто пам’ять поступово не використовується, як працює сценарій.

  2. Я додав close_fds = True до виклику Popen, але це не мало значення - сценарій все ще вийшов із тієї самої помилки. Запропоновано тут і тут .

  3. Я перевірив обмеження, які показували (-1, -1) і на RLIMIT_DATA, і на RLIMIT_AS, як тут запропоновано .

  4. Стаття запропонувала, що не має простір підкачки не може бути причиною , але заміна насправді за запитом ( в залежності від інтернету - хостингу) , і це також було запропоновано в якості підроблених привести тут .

  5. Процеси закриваються, тому що це поведінка використання .communicate () підкріпленого вихідним кодом Python та коментарями тут .

Цілі перевірки можна знайти на сайті GitHub за допомогою функції getProcess, визначеної з рядка 442. Це викликається doChecks (), починаючи з рядка 520.

Сценарій був запущений з strace із наступним висновком перед збоєм:

recv(4, "Total Accesses: 516662\nTotal kBy"..., 234, 0) = 234
gettimeofday({1250893252, 887805}, NULL) = 0
write(3, "2009-08-21 17:20:52,887 - checks"..., 91) = 91
gettimeofday({1250893252, 888362}, NULL) = 0
write(3, "2009-08-21 17:20:52,888 - checks"..., 74) = 74
gettimeofday({1250893252, 888897}, NULL) = 0
write(3, "2009-08-21 17:20:52,888 - checks"..., 67) = 67
gettimeofday({1250893252, 889184}, NULL) = 0
write(3, "2009-08-21 17:20:52,889 - checks"..., 81) = 81
close(4)                                = 0
gettimeofday({1250893252, 889591}, NULL) = 0
write(3, "2009-08-21 17:20:52,889 - checks"..., 63) = 63
pipe([4, 5])                            = 0
pipe([6, 7])                            = 0
fcntl64(7, F_GETFD)                     = 0
fcntl64(7, F_SETFD, FD_CLOEXEC)         = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7f12708) = -1 ENOMEM (Cannot allocate memory)
write(2, "Traceback (most recent call last"..., 35) = 35
open("/usr/bin/sd-agent/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/bin/sd-agent/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python24.zip/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/plat-linux2/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python2.4/lib-tk/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/lib-dynload/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/site-packages/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
write(2, "  File \"/usr/bin/sd-agent/agent."..., 52) = 52
open("/home/admin/sd-agent/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/bin/sd-agent/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python24.zip/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/plat-linux2/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python2.4/lib-tk/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/lib-dynload/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/site-packages/daemon.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
write(2, "  File \"/home/admin/sd-agent/dae"..., 60) = 60
open("/usr/bin/sd-agent/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/bin/sd-agent/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python24.zip/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/plat-linux2/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python2.4/lib-tk/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/lib-dynload/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/site-packages/agent.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
write(2, "  File \"/usr/bin/sd-agent/agent."..., 54) = 54
open("/usr/lib/python2.4/sched.py", O_RDONLY|O_LARGEFILE) = 8
write(2, "  File \"/usr/lib/python2.4/sched"..., 55) = 55
fstat64(8, {st_mode=S_IFREG|0644, st_size=4054, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d28000
read(8, "\"\"\"A generally useful event sche"..., 4096) = 4054
write(2, "    ", 4)                     = 4
write(2, "void = action(*argument)\n", 25) = 25
close(8)                                = 0
munmap(0xb7d28000, 4096)                = 0
open("/usr/bin/sd-agent/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/bin/sd-agent/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python24.zip/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/plat-linux2/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python2.4/lib-tk/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/lib-dynload/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/site-packages/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
write(2, "  File \"/usr/bin/sd-agent/checks"..., 60) = 60
open("/usr/bin/sd-agent/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/bin/sd-agent/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python24.zip/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/plat-linux2/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOMEM (Cannot allocate memory)
open("/usr/lib/python2.4/lib-tk/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/lib-dynload/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.4/site-packages/checks.py", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
write(2, "  File \"/usr/bin/sd-agent/checks"..., 64) = 64
open("/usr/lib/python2.4/subprocess.py", O_RDONLY|O_LARGEFILE) = 8
write(2, "  File \"/usr/lib/python2.4/subpr"..., 65) = 65
fstat64(8, {st_mode=S_IFREG|0644, st_size=39931, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d28000
read(8, "# subprocess - Subprocesses with"..., 4096) = 4096
read(8, "lso, the newlines attribute of t"..., 4096) = 4096
read(8, "code < 0:\n        print >>sys.st"..., 4096) = 4096
read(8, "alse does not exist on 2.2.0\ntry"..., 4096) = 4096
read(8, " p2cread\n        # c2pread    <-"..., 4096) = 4096
write(2, "    ", 4)                     = 4
write(2, "errread, errwrite)\n", 19)    = 19
close(8)                                = 0
munmap(0xb7d28000, 4096)                = 0
open("/usr/lib/python2.4/subprocess.py", O_RDONLY|O_LARGEFILE) = 8
write(2, "  File \"/usr/lib/python2.4/subpr"..., 71) = 71
fstat64(8, {st_mode=S_IFREG|0644, st_size=39931, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7d28000
read(8, "# subprocess - Subprocesses with"..., 4096) = 4096
read(8, "lso, the newlines attribute of t"..., 4096) = 4096
read(8, "code < 0:\n        print >>sys.st"..., 4096) = 4096
read(8, "alse does not exist on 2.2.0\ntry"..., 4096) = 4096
read(8, " p2cread\n        # c2pread    <-"..., 4096) = 4096
read(8, "table(self, handle):\n           "..., 4096) = 4096
read(8, "rrno using _sys_errlist (or siml"..., 4096) = 4096
read(8, " p2cwrite = None, None\n         "..., 4096) = 4096
write(2, "    ", 4)                     = 4
write(2, "self.pid = os.fork()\n", 21)  = 21
close(8)                                = 0
munmap(0xb7d28000, 4096)                = 0
write(2, "OSError", 7)                  = 7
write(2, ": ", 2)                       = 2
write(2, "[Errno 12] Cannot allocate memor"..., 33) = 33
write(2, "\n", 1)                       = 1
unlink("/var/run/sd-agent.pid")         = 0
close(3)                                = 0
munmap(0xb7e0d000, 4096)                = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x589978}, {0xb89a60, [], SA_RESTORER, 0x589978}, 8) = 0
brk(0xa022000)                          = 0xa022000
exit_group(1)                           = ?

1
запущений з 'pipe' або fileescriptors або ресурс ядра, пов'язаний з ними?
Blauohr

Перевірте /var/log/messagesчи dmesgкомандуйте.
mark4o

У журналі, що стосується цього, немає нічого.
davidmytton

Ви коли-небудь отримували рішення на це? У мене дуже схожі симптоми. У мене багато запасної пам’яті, але після додавання свопу (як це підказує деякі ваші відповіді) проблема усувається. Просто цікавилося, чи знайшли ви щось у місяці між тоді і тепер. -- Дякую!
dpb

Я зіткнувся з тією ж проблемою, але без вирішення - будь-які ідеї?

Відповіді:


88

За загальним правилом (тобто в ваніль насіння), fork/ cloneзбої з ENOMEM відбуваються саме з - або чесний до Бога поза пам'яті стану ( dup_mm, dup_task_struct, alloc_pid, mpol_dup, і mm_initт.д. каркати), або тому , що security_vm_enough_memory_mmне вдалося вам , а виконання в overcommit політику .

Почніть з перевірки vmsize процесу, який не вдалося розщедритися, під час спроби вилки, а потім порівняйте з кількістю вільної пам'яті (фізичної та своп), як це стосується політики перевиконання (підключіть номери.)

У вашому конкретному випадку зауважте, що Virtuozzo має додаткові перевірки при дотриманні примусового виконання . Більше того, я не впевнений, наскільки ви справді маєте контроль зсередини свого контейнера над конфігурацією swap та overcommit (щоб вплинути на результат правозастосування.)

Тепер, щоб насправді рухатись вперед, я б сказав, що вам залишаються два варіанти :

  • перейти на більший екземпляр, або
  • поставити деякі роботи по кодування в більш ефективному контролі пам'яті вашого скрипта сліду

Зверніть увагу, що зусилля з кодування можуть бути зведені нанівець, якщо виявиться, що це не ви, а якийсь інший хлопець, розміщений в іншому екземплярі на тому ж сервері, що і ви працюєте в амоці.

На пам'ять, ми вже знаємо, що subprocess.Popenвикористовує fork/ clone під кришкою , тобто кожен раз, коли ви його викликаєте, ви вимагаєте ще раз стільки пам’яті, скільки Python вже з'їдає , тобто в сотні додаткових МБ, все для того, щоб потім execневиконаний 10 Кб виконуваний файл, наприклад, freeабо ps. У випадку несприятливої ​​політики перевиконання, ви незабаром побачите ENOMEM.

Альтернативи forkцьому не мають таблиці батьківських сторінок тощо. Проблема копіювання є vforkі posix_spawn. Але якщо ви не відчуваєте, як переписувати шматки з subprocess.Popenточки зору vfork/ posix_spawn, подумайте скористатись suprocess.Popenлише один раз на початку свого сценарію (коли пам’ять пам’яті Python мінімальна), щоб породити скрипт оболонки, який потім запускається free/ ps/ sleepі все інше в цикл, паралельний вашому сценарію; опитуйте висновок сценарію або читайте його синхронно, можливо, з окремої нитки, якщо у вас є інші речі, щоб подбати про асинхронність - виконайте обробку даних у Python, але залиште розгортання підлеглому процесу.

ЗАРАЗ , у вашому конкретному випадку ви можете пропустити посилання psта freeвзагалі; що ця інформація легко доступна вам у Python безпосередньо зprocfs того, незалежно від того, ви вирішите отримати доступ до неї самостійно або через наявні бібліотеки та / або пакети . Якщо psі freeбули єдиними утилітами, якими ви працювали, то ви можете повністю позбутисяsubprocess.Popen .

Нарешті, що б ви не робили subprocess.Popen, якщо ваш сценарій просочується пам'яттю, ви все одно вдаритеся до стіни. Слідкуйте за цим і перевірте на наявність витоків пам'яті .


7
Я виявив, що запуск gc.collect()безпосередньо перед тим subprocess.Popenдопомагає у випадках, коли сміттєзбірник не працював деякий час.
letmaik

Я написав deamon для розробки стратегії допоміжного сценарію: github.com/SeanHayes/errand-boy Я використовую його у виробництві з одним із своїх клієнтів, і наші проблеми "Неможливо виділити пам'ять" пішли з ладу.
Seán Hayes

Я буду вдячний за просту діагностику, наприклад, наступне, /proc/fd/mapsщоб визначити, чи справді проблема
перезавантаженої

18

Дивлячись на вихід, free -mмені здається, що ви фактично не маєте пам’яті свопу. Я не впевнений, чи в Linux заміни завжди будуть доступні автоматично на вимогу, але у мене виникли однакові проблеми, і жоден з відповідей тут мені не допоміг. Додавання обмінної пам’яті вирішило проблему в моєму випадку, тому що це може допомогти іншим людям, які стикаються з тією ж проблемою, я розміщую свою відповідь про те, як додати своп 1 Гб (на Ubuntu 12.04, але це має працювати аналогічно для інших дистрибутивів).

Спочатку ви можете перевірити, чи ввімкнено якусь пам'ять підкачки

$sudo swapon -s

якщо він порожній, це означає, що ви не ввімкнули жодного свопу. Щоб додати своп 1 Гб:

$sudo dd if=/dev/zero of=/swapfile bs=1024 count=1024k
$sudo mkswap /swapfile
$sudo swapon /swapfile

Додайте наступний рядок до, fstabщоб зробити своп постійним.

$sudo vim /etc/fstab

     /swapfile       none    swap    sw      0       0 

Джерело та більше інформації можна знайти тут .


1
Це вирішило ту саму проблему чи якусь іншу?
Діма Тиснек

Це зробили для мене на CentOS 6.4. Зіткнулася з помилкою під час встановлення айстратів, дякую.
Руслан Абузант

Хоча це дозволило мені виконати Кодекс, він насправді не вирішив проблему, яка, ймовірно, лежить у бібліотеці, яку я використовую.
philmaweb

1
Ви вирішили мою проблему. Дякую! +1
sscirrus

8

своп може бути не попередньо запропонованою червоною оселедцем. Наскільки великий процес пітону, про який йде мова, безпосередньо перед ENOMEM?

У ядрі 2.6 /proc/sys/vm/swappinessконтролюється, наскільки агресивно ядро ​​перетвориться на своп, а також overcommit*файли, наскільки і наскільки точно ядро ​​може розподілити пам'ять підморгнутим і кивком. Як і ваш статус стосунків у Facebook, це складно .

... але обмін фактично доступний на вимогу (за даними веб-хоста) ...

але не відповідно до результатів вашої free(1)команди, яка не показує місця заміни, розпізнаного вашим екземпляром сервера. Тепер ваш веб-хост, безумовно, знає набагато більше, ніж я, про цю тему, але віртуальні системи RHEL / CentOS, якими я користувався, повідомили про заміну, доступну для гостьової ОС.

Адаптація Red Hat KB Стаття 15252 :

Система Red Hat Enterprise Linux 5 буде працювати нормально, не змінюючи місця для обміну, доки сума анонімної пам’яті та загальної пам’яті системи V становить менше приблизно 3/4 обсягу оперативної пам’яті. .... Системи з 4 ГБ оперативної пам’яті або менше [рекомендується мати] мінімум 2 Гб місця для обміну.

Порівняйте свої /proc/sys/vmналаштування із звичайною установкою CentOS 5.3. Додайте файл свопу. Вгамуйте swappinessі подивіться, чи живете ви більше.


Який найкращий спосіб перевірити розмір процесу python? ps?
davidmytton

щось подібне ps -o user,pid,vsz="Mem(Kb)" -o cmd $PYTHON_PID, або top (1), має це зробити.
стовп


5

Я продовжую підозрювати, що у вашого клієнта / користувача є завантажений модуль ядра або драйвер, який заважає clone()системному виклику (можливо, якесь незрозуміле покращення безпеки, щось на зразок LIDS, але більш незрозуміле?) Або якимось чином заповнює деякі структури даних ядра, які необхідні для fork()/ clone()для роботи (таблиця процесів, таблиці сторінок, таблиці дескрипторів файлів тощо).

Ось відповідна частина fork(2)чоловічої сторінки:

ПОМИЛКИ
       EAGAIN fork () не може виділити достатню кількість пам'яті для копіювання таблиць батьківських сторінок та виділення структури завдань для
              дитина.

       EAGAIN Не вдалося створити новий процес, тому що встановлено обмеження ресурсу RLIMIT_NPROC абонента. До
              перевищувати цю межу, процес повинен мати або CAP_SYS_ADMIN, або CAP_SYS_RESOURCE.

       ENOMEM fork () не вдалося виділити необхідну структуру ядра, оскільки пам'ять обмежена.

Я пропоную користувачеві спробувати це після завантаження в запас, загальне ядро ​​і лише мінімальний набір модулів і драйверів, завантажених (мінімум, необхідний для запуску програми / сценарію). Звідси, якщо припустити, що він працює в цій конфігурації, вони можуть здійснювати бінарний пошук між цим і конфігурацією, яка демонструє проблему. Це стандартне усунення несправностей у системі sysadmin 101.

Відповідний рядок у вашому strace:

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7f12708) = -1 ENOMEM (Cannot allocate memory)

... Я знаю, що інші говорили про доступ до swap та пам'яті (і я б рекомендував вам встановити принаймні невеликий розділ swap, за іронією долі, навіть якщо він знаходиться на диску оперативної пам'яті ... кодові шляхи через ядро ​​Linux, коли у нього є навіть невеликий доступний обмін свопом був здійснений набагато ширше, ніж ті (шляхи обробки винятків), у яких доступний нульовий своп.

Однак я підозрюю, що це все-таки червона оселедець.

Той факт, що freeповідомляє 0 (ZERO) пам’яті, що використовується кешем та буферами, дуже заважає. Я підозрюю, що freeвихід ... і, можливо, проблема з вашим додатком тут, викликані деяким власницьким модулем ядра, який певним чином заважає розподілу пам'яті.

Згідно з довідковими сторінками для fork () / clone () системний виклик fork () повинен повернути EAGAIN, якщо ваш виклик призведе до порушення ліміту ресурсів (RLIMIT_NPROC) ... однак він не говорить про те, чи потрібно повертати EAGAIN іншими порушеннями RLIMIT *. У будь-якому випадку, якщо у вашої цілі / хоста є якісь дивні Vormetric або інші налаштування безпеки (або навіть якщо ваш процес працює за якоюсь дивною політикою SELinux), це може спричинити цю помилку -ENOMEM.

Це навряд чи буде нормальною проблемою Linux / UNIX. У вас там відбувається щось нестандартне.


1
Сервер працює на базі Media Template (dv), який використовує Virtuozzo для віртуалізації.
davidmytton

Спробуйте пошукати дошки оголошень Virtuozzo та систему відстеження помилок і, можливо, шукайте оновлення самої підсистеми Virtuozzo.
Джим Денніс

2

Ви спробували використовувати:

(status,output) = commands.getstatusoutput("ps aux")

Я думав, що це вирішило саме таку проблему для мене. Але тоді мій процес закінчився вбивством, а не нерестом, що ще гірше.

Після деяких тестувань я виявив, що це сталося лише на старих версіях python: це відбувається з 2.6.5, але не з 2.7.2

Мій пошук привів мене сюди до python-close_fds-problem , але невстановлення closed_fds не вирішило проблему. Це все-таки варто прочитати.

Я виявив, що python просочував дескриптори файлів, просто стежачи за цим:

watch "ls /proc/$PYTHONPID/fd | wc -l"

Як і ви, я хочу зафіксувати результати команди, і я хочу уникати помилок OOM ... але, схоже, єдиний спосіб полягає в тому, щоб люди могли використовувати менш глючну версію Python. Не ідеально ...


0

munmap (0xb7d28000, 4096) = 0
написати (2, "OSError", 7) = 7

Я бачив неохайний код, який виглядає приблизно так:

serrno = errno;
some_Syscall(...)
if (serrno != errno)
/* sound alarm: CATROSTOPHIC ERROR !!! */

Ви повинні перевірити, чи не відбувається це в коді python. Errno дійсний лише в тому випадку, якщо системний виклик, що триває, не вдався.

Відредаговано, щоб додати:

Ви не кажете, як довго триває цей процес. Можливі споживачі пам'яті

  • роздвоєні процеси
  • невикористані структури даних
  • спільні бібліотеки
  • файли, відображені в пам'яті

2
Так, але з точки зору ОП ми бачимо, що перша помилка системного виклику - від клона () - це ENOMEM, як повідомляється. Ця помилка зберігається під час спотикання низької пам’яті python за допомогою побудови слідів зворотного зв'язку, навіть незважаючи на те, що C-бібліотека errnoбагато разів скидається по дорозі.
pilcrow

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.