Node.js fängt den nach dem Spawn ausgelösten ENOMEM-Fehler ab

82

Mein Node.js-Skript stürzt aufgrund einer ausgelösten ENOMEM-ErrnoException (nicht genügend Speicher) ab, wenn Spawn verwendet wird .

Der Fehler:

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)

Ich verwende bereits Listener für das Ereignis errorund exit, aber keiner von ihnen wird im Falle dieses Fehlers gefeuert.

Mein Code:

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

Vollständiger Quellcode verfügbar .

Kann ich irgendetwas tun, um zu verhindern, dass das Skript abstürzt? Wie fange ich den ausgelösten ENOMEM-Fehler ab?

Vielen Dank!

tobi
quelle
Haben Sie ein Beispielbild, mit dem Sie das Problem replizieren können?
mscdex
Dies passiert, wenn der Server nicht genügend Speicher hat und nicht mit einem bestimmten Image reproduziert werden kann. Das macht es schwer zu testen: - /
tobi
Was machst du im errorHandler?
mscdex
1
Haben Sie eine Lösung für dieses Problem gefunden?
sffc
2
Ich denke, dies ist ein grundlegender Fehler bei der Verwendung fork()(des zugrunde liegenden Systemaufrufs). Siehe github.com/nodejs/node/issues/25382
ZachB

Antworten:

200

Ich hatte das gleiche Problem und wie sich herausstellte, war auf meinem System kein Swap Space aktiviert . Überprüfen Sie, ob dies der Fall ist, indem Sie den folgenden Befehl ausführen 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

Wenn wir uns die untere Reihe ansehen, sehen wir, dass wir insgesamt 0 Byte Swap-Speicher haben. Nicht gut. Der Knoten kann ziemlich speicherhungrig werden, und wenn kein Speicherplatz verfügbar ist, wenn der Speicher knapp wird, können Fehler auftreten.

Die Methode zum Hinzufügen einer Auslagerungsdatei variiert zwischen Betriebssystemen und Distributionen. Wenn Sie jedoch Ubuntu wie mich ausführen, können Sie beim Hinzufügen einer Auslagerungsdatei die folgenden Anweisungen befolgen :

  1. sudo fallocate -l 4G /swapfile Erstellen Sie eine 4-Gigabyte-Auslagerungsdatei
  2. sudo chmod 600 /swapfile Sichern Sie die Auslagerungsdatei, indem Sie den Zugriff auf root einschränken
  3. sudo mkswap /swapfile Markieren Sie die Datei als Swap Space
  4. sudo swapon /swapfile Aktivieren Sie den Swap
  5. echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstabTauschen Sie die Swap-Datei über Neustarts aus (danke für den Tipp, bman !)
Kaivosukeltaja
quelle
14
Nur eine Notiz für alle, die diese Antwort in Zukunft lesen. Swapfile bleibt beim Neustart nicht bestehen. Um es dauerhaft zu machen, müssen Sie die Datei / etc / fstab bearbeiten und am Ende eine Zeile hinzufügen: / swapfile none swap sw 0 0
bman
Nur meine dumme VM 2 weitere Gigs RAM zu geben, löste mein oben genanntes Problem.
Thomson Comer
2
Ist das eine gute Idee auf einem Produktionsserver? Meines Wissens nach kann sich die Leistung stark verschlechtern, wenn das Betriebssystem Swap-Speicher verwendet. Daher ist es besser, den Server mit genügend RAM zu dimensionieren, um die Anforderungen der Anwendungen zu erfüllen, und Speicherlecks aggressiv aufzuspüren.
Josh
2
@josh, wenn der Arbeitsspeicher knapp wird, geschieht eines von zwei Dingen: Entweder wird der Speicher in eine Auslagerungsdatei ausgelagert, oder Anforderungen an zusätzlichen Speicher schlagen mit unerwarteten Ergebnissen fehl. Ja, die Leistung kann sich verschlechtern, wenn eine Swap-Datei verwendet wird, aber ich werde das jeden Tag über die andere Option stellen, insbesondere in der Produktion.
Kaivosukeltaja
Ich habe den Speicher nicht verdoppelt und muss die Größe ändern? Wie mache ich das?
Jack
4

Wenn Sie in AWS Lambda jemals auf dieses Problem stoßen, sollten Sie in Betracht ziehen, den der Funktion zugewiesenen Speicher zu erhöhen.

James Shapiro
quelle
2

Sie können versuchen, die Menge des verwendeten Speicherknotens mit diesem Befehl zu ändern: node ----max-old-space-size=1024 yourscript.js

--max-old-space-size = 1024 weist 1 Gig Speicher zu.

Standardmäßig verwendet der Knoten 512 MB RAM. Abhängig von Ihrer Plattform müssen Sie möglicherweise mehr oder weniger zuweisen, damit die Speicherbereinigung bei Bedarf aktiviert wird.

Wenn auf Ihrer Plattform weniger als 500 MB RAM verfügbar sind, versuchen Sie, die Speichernutzung auf --max-old-space-size = 256 zu senken.

Deemoe
quelle
1

Ich hatte das gleiche Problem und habe es mit try / catch behoben:

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

Ich habe das Problem behoben, indem ich meinen Knotenserver nur deaktiviert und wieder aktiviert habe.

Carlos G.
quelle
-5

Sie müssen die Ausgänge aus dem aufgerufenen Prozess spülen!

Ein Python-Beispiel sieht folgendermaßen aus:

import sys
...
sys.stdout.flush()
Tim Long
quelle
Es ist keine Python