Node.js detecta el error ENOMEM lanzado después del spawn


82

Mi script de Node.js se bloquea debido a una excepción errnoException de ENOMEM (memoria insuficiente) al usar spawn .

El error:

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)

Ya estoy usando oyentes para el evento errory exit, pero ninguno de ellos es despedido en caso de este error.

Mi código:

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

Código fuente completo disponible .

¿Hay algo que pueda hacer para evitar que el script se bloquee? ¿Cómo detecto el error ENOMEM lanzado?

¡Gracias!


¿Tiene una imagen de ejemplo que se pueda usar para replicar el problema?
mscdex

Ocurre cuando el servidor se queda sin memoria y no se puede reproducir con una imagen en particular. Eso hace que sea difícil de probar: - /
tobi

¿Qué estás haciendo dentro del errorcontrolador?
mscdex

1
¿Encontraste una solución a este problema?
sffc

2
Creo que este es un defecto fundamental al usar fork()(la llamada al sistema subyacente). Ver github.com/nodejs/node/issues/25382
ZachB

Respuestas:


201

Tuve el mismo problema y resultó que mi sistema no tenía espacio de intercambio habilitado . Verifique si este es el caso ejecutando el comando 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

Mirando la fila inferior podemos ver que tenemos un total de memoria de intercambio de 0 bytes. No está bien. El nodo puede consumir bastante memoria y si no hay espacio de intercambio disponible cuando se agota la memoria, es probable que se produzcan errores.

El método para agregar un archivo de intercambio varía entre sistemas operativos y distribuciones, pero si está ejecutando Ubuntu como yo, puede seguir estas instrucciones para agregar un archivo de intercambio :

  1. sudo fallocate -l 4G /swapfile Cree un archivo de intercambio de 4 gigabytes
  2. sudo chmod 600 /swapfile Asegure el archivo de intercambio restringiendo el acceso a la raíz
  3. sudo mkswap /swapfile Marcar el archivo como espacio de intercambio
  4. sudo swapon /swapfile Habilita el intercambio
  5. echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstabPersistir el archivo de intercambio durante los reinicios (¡gracias por el consejo, bman !)

14
Solo una nota para cualquier persona en el futuro que esté leyendo esta respuesta. Swapfile no es persistente al reiniciar. Para que sea persistente, debe editar el archivo / etc / fstab y agregar una línea al final: / swapfile none swap sw 0 0
bman

Solo darle a mi estúpida VM 2 gigas más de RAM resolvió mi problema anterior.
Thomson Comer

2
¿Es esta una buena idea en un servidor de producción? Tengo entendido que cuando el sistema operativo comienza a usar memoria de intercambio, el rendimiento puede degradarse drásticamente, por lo que es mejor dimensionar su servidor con suficiente RAM para manejar las necesidades de las aplicaciones y buscar agresivamente las fugas de memoria.
Josh

2
@josh, cuando la RAM se agota, sucederá una de dos cosas: la memoria se paginará en un archivo de intercambio o cualquier solicitud de memoria adicional fallará con resultados inesperados. Sí, el rendimiento puede degradarse cuando se usa un archivo de intercambio, pero lo tomaré cualquier día sobre la otra opción, especialmente en producción.
Kaivosukeltaja

¿No hice el doble de memoria y necesito cambiar el tamaño? ¿Cómo hago esto?
Jack

4

Si alguna vez se encuentra con este problema en AWS Lambda, debería considerar aumentar la memoria asignada a la función.


2

Puede intentar cambiar la cantidad de memoria que utiliza el nodo con este comando: node ----max-old-space-size=1024 yourscript.js

--max-old-space-size = 1024 asignará 1 giga de memoria.

Por defecto, el nodo usará 512 MB de RAM, pero dependiendo de su plataforma, es posible que deba asignar más o menos para que la recolección de basura se active cuando la necesite.

Si su plataforma tiene menos de 500 mb de RAM disponible, intente configurar el uso de memoria más bajo a --max-old-space-size = 256.


1

Tuve el mismo problema y lo solucioné con try / catch:

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

0

Solucioné el problema simplemente desactivando y volviendo a activar mi servidor de nodo.


-5

¡Tienes que eliminar las salidas del proceso llamado!

Un ejemplo de Python se ve así:

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

no es una pitón
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.