Node.js, yumurtlamadan sonra atılan ENOMEM hatasını yakalar


84

Node.js betiğim, spawn kullanılırken atılan bir ENOMEM (Bellek yetersiz) errnoException nedeniyle çöküyor .

Hata:

child_process.js:935
  throw errnoException(process._errno, 'spawn');
        ^

Error: spawn ENOMEM
  at errnoException (child_process.js:988:11)
  at ChildProcess.spawn (child_process.js:935:11)
  at Object.exports.spawn (child_process.js:723:9)
  at module.exports ([...]/node_modules/zbarimg/index.js:19:23)

Zaten errorve exitolayı için dinleyiciler kullanıyorum , ancak bu hata durumunda hiçbiri kovulmuyor.

Kodum:

zbarimg = process.spawn('zbarimg', [photo, '-q']);
zbarimg.on('error', function(err) { ... });
zbarimg.on('close', function(code) { ... }); 

Tam kaynak kodu mevcut .

Komut dosyasının çökmesini önlemek için yapabileceğim herhangi bir şey var mı? Atılan ENOMEM hatasını nasıl yakalarım?

Teşekkürler!


Sorunu tekrarlamak için kullanılabilecek bir örnek görüntünüz var mı?
mscdex

Sunucu hafızası tükendiğinde ve belirli bir görüntü ile yeniden üretilemediğinde gerçekleşir. Bu test etmeyi zorlaştırıyor: - /
tobi

errorİşleyicinin içinde ne yapıyorsun ?
mscdex

1
Bu soruna bir çözüm buldunuz mu?
sffc

2
Bunun fork()(temel sistem çağrısı) kullanmanın temel bir kusuru olduğunu düşünüyorum . Bkz. Github.com/nodejs/node/issues/25382
ZachB

Yanıtlar:


204

Aynı sorunu yaşadım ve ortaya çıktığı gibi, sistemimde takas alanı etkin değildi . Komutu çalıştırarak durumun bu olup olmadığını kontrol edin free -m:

vagrant@vagrant-ubuntu-trusty-64:~$ free -m
             total       used       free     shared    buffers     cached
Mem:          2002        233       1769          0         24         91
-/+ buffers/cache:        116       1885
Swap:            0          0          0

Alt satıra baktığımızda toplam 0 bayt takas belleğimiz olduğunu görebiliriz. İyi değil. Düğüm, belleğe oldukça aç olabilir ve bellek bittiğinde takas alanı yoksa, hataların olması kaçınılmazdır.

Takas dosyası ekleme yöntemi, işletim sistemleri ve dağıtımlar arasında farklılık gösterir, ancak benim gibi Ubuntu'yu çalıştırıyorsanız , takas dosyası eklemek için aşağıdaki talimatları uygulayabilirsiniz :

  1. sudo fallocate -l 4G /swapfile 4 gigabaytlık bir takas dosyası oluşturun
  2. sudo chmod 600 /swapfile Kök erişimini kısıtlayarak takas dosyasını güvenli hale getirin
  3. sudo mkswap /swapfile Dosyayı takas alanı olarak işaretleyin
  4. sudo swapon /swapfile Değişimi etkinleştirin
  5. echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstabYeniden başlatmalar üzerinde takas dosyasını sürdürün (ipucu için teşekkürler, bman !)

15
Gelecekte bu cevabı okuyacak olan herkes için bir not. Swapfile, yeniden başlatmalarda kalıcı değildir. Kalıcı olmasını sağlamak için / etc / fstab dosyasını düzenlemeniz ve sonuna bir satır eklemeniz gerekir: / swapfile none swap swap 0 0
bman

Aptal VM 2'ye daha fazla ram vermem bile yukarıdaki sorunumu çözdü.
Thomson Comer

2
Bu bir üretim sunucusunda iyi bir fikir mi? Anladığım kadarıyla, işletim sistemi takas belleği kullanmaya başladığında, performans keskin bir şekilde düşebilir, bu nedenle sunucunuzu uygulamaların ihtiyaçlarını karşılayacak kadar yeterli RAM ile boyutlandırmak ve bellek sızıntılarını agresif bir şekilde avlamak daha iyidir.
josh

2
@josh, RAM bittiğinde iki şeyden biri olur - bellek takas dosyasına sayfalanır veya herhangi bir ek bellek talebi beklenmedik sonuçlarla başarısız olur. Evet, takas dosyası kullanıldığında performans düşebilir, ancak bunu her gün, özellikle üretimde diğer seçeneğin üzerine alacağım .
Kaivosukeltaja

Hafızayı ikiye katlamadım ve yeniden boyutlandırmam mı gerekiyor? Bunu nasıl yaparım?
Jack

5

AWS Lambda'da bu sorunla karşılaşırsanız, işleve ayrılan belleği artırmayı düşünmelisiniz.


2

Bu komutla kullanılan bellek düğümü miktarını değiştirmeyi deneyebilirsiniz: node ----max-old-space-size=1024 yourscript.js

--max-old-space-size = 1024, 1 gig bellek ayırır.

Varsayılan olarak node 512 mb ram kullanır ancak platformunuza bağlı olarak daha fazla veya daha az ayırmanız gerekebilir, böylece çöp toplama ihtiyacınız olduğunda devreye girer.

Platformunuzda 500 mb'den daha az kullanılabilir ram varsa, bellek kullanımını --max-old-space-size = 256'ya düşürmeyi deneyin.


1

Aynı sorunu yaşadım ve dene / yakala ile düzelttim:

try {
  zbarimg = process.spawn('zbarimg', [photo, '-q']);
} catch (err) {
  console.log(err);
}
zbarimg.on('error', function(err) { ... });
zbarimg.on('close', function(code) { ... }); 

0

Düğüm Sunucumu devre dışı bırakıp yeniden etkinleştirerek sorunu çözdüm.


-6

Çağrılan işlemden çıktıları temizlemelisiniz!

Bir python örneği şuna benzer:

import sys
...
sys.stdout.flush()

bu bir python değil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.