Estoy ejecutando pdftoppm
para convertir un PDF proporcionado por el usuario en una imagen de 300 DPI. Esto funciona muy bien, excepto si el usuario proporciona un PDF con un tamaño de página muy grande. pdftoppm
asignará suficiente memoria para almacenar una imagen de 300 ppp de ese tamaño en la memoria, que para una página cuadrada de 100 pulgadas es 100*300 * 100*300 * 4 bytes por píxel =3,5 GB. Un usuario malintencionado podría darme un PDF demasiado grande y causar todo tipo de problemas.
Entonces, lo que me gustaría hacer es poner algún tipo de límite estricto en el uso de la memoria para un proceso secundario que estoy a punto de ejecutar, solo hacer que el proceso muera si intenta asignar más de, digamos, 500 MB de memoria. ¿Es eso posible?
No creo que ulimit se pueda usar para esto, pero ¿hay un equivalente de un proceso?
Respuesta aceptada:
Hay algunos problemas con ulimit. Aquí hay una lectura útil sobre el tema:Limitar el tiempo y el consumo de memoria de un programa en Linux, lo que conduce a la herramienta de tiempo de espera, que le permite encerrar un proceso (y sus bifurcaciones) por tiempo o consumo de memoria.
La herramienta de tiempo de espera requiere Perl 5+ y /proc
sistema de archivos montado. Después de eso, copia la herramienta a, p. /usr/local/bin
así:
curl https://raw.githubusercontent.com/pshved/timeout/master/timeout |
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout
Después de eso, puede 'enjaular' su proceso por consumo de memoria como en su pregunta así:
timeout -m 500 pdftoppm Sample.pdf
Alternativamente, podría usar -t <seconds>
y -x <hertz>
para limitar respectivamente el proceso por tiempo o restricciones de CPU.
La forma en que funciona esta herramienta es comprobando varias veces por segundo si el proceso generado no ha superado los límites establecidos. Esto significa que en realidad hay una pequeña ventana donde un proceso podría potencialmente suscribirse en exceso antes de los avisos de tiempo de espera y matar el proceso.
Por lo tanto, un enfoque más correcto probablemente involucraría cgroups, pero eso es mucho más complicado de configurar, incluso si usa Docker o runC, que entre otras cosas, ofrecen una abstracción más fácil de usar en torno a cgroups.