La semana pasada la persona responsable de la administración de la plataforma Moodle de nuestra institución me comentó que estaban teniendo problemas con el envío de mails de notificaciones de los foros. Simplemente ni estaba llegando ninguna notificación de novedades en los foros. Pero lo más extraño era que el resto del envío de mails de Moodle (por ejemplo recupero de contraseñas de usuarios) sí estaban funcionando, lo cual descartaba cualquier tipo de problema con el servidor de correo.

El envío de notificaciones por mail relacionadas a los foros se hace a través de una tarea programada en el proceso cron de Moodle. Más precisamente lo hace la tarea "\mod_forum\task\cron_task". Al revisar el log del proceso cron, me encontré con que esta tarea no se estaba ejecutando desde un par de días.

Además, al lanzar el proceso cron de forma manual:

root@debian:~# su www-data -c '/usr/bin/php /var/www/moodle/admin/cli/cron.php'

Se ejecutaban todas las tareas pendientes excepto la tarea "\mod_forum\task\cron_task", a pesar de que estuviese planificada como ASAP (as soon as possible).

Tal como expliqué en el artículo Listar y ejecutar manualmente las tareas programadas de Moodle desde línea de comandos, intenté ejecutar esta tarea de forma manual:

root@debian:~# su www-data -c '/usr/bin/php /var/www/moodle/admin/tool/task/cli/schedule_task.php --execute=\\mod_forum\\task\\cron_task'

Lo que arrojó el error:

Cannot obtain task lock

Obviamente la tarea no se ejecutó y sólo se mostró este misterioso error.

Lo que sucede es que Moodle utiliza un mecanismo de locks (por defecto implementado a nivel filesystem, aunque también puede ser implementado a nivel base de datos, según como esté configurada la variable $CFG->lock_factory en el archivo config.php) para que la ejecución de una misma tarea no se solape, y así evitar errores e inconsistencias. Esto es necesario porque, si el proceso cron de Moodle se ejecuta en cada minuto y una tarea que también se ejecuta en cada minuto demora más de un minuto, se lanzarían múltiples instancias de una misma tarea de forma simultánea, lo que podría provocar errores e inconsistencias (sin contar con que se corre el riesgo de que se acumulen procesos compitiendo por un mismo recurso). Es posible ver qué locks utiliza el sistema consultando la tabla "mdl_lock_db".

Si se están utilizando locks a nivel sistema de archivos (configuración por defecto) y se encuentra el error "Cannot obtain task lock", significa que algún proceso está bloqueando el acceso a los archivos necesarios. Por ende, la solución consiste en comprobar que no haya quedado una instancia del proceso cron de Moodle en ejecución de forma indefinida ("colgada"). Para ello simplemente analizar la salida de ps ejecutando:

# ps aux | grep cron.php

Y, en caso de encontrar una (o más de una) instancia del proceso cron.php, determinar la fecha de creación del proceso listando el directorio correspondiente a su PID dentro del directorio /proc:

# ls -od --time-style='+%F %T' /proc/[PID]

Si hay un único proceso en ejecución, y su fecha de creación no es cercana a la fecha actual (date), significa que se trata de una instancia del proceso cron de Moodle que ha quedado "colgada". Matando el proceso se liberan los locks y se soluciona el problema. Si hay más de un proceso en ejecución (la hora actual coincide con el período de ejecución programado para el proceso cron), aquel cuya fecha de creación sea más antigua es el que está "colgado" y es necesario terminarlo (kill o kill -9 si no responde).

Referencias

Scheduled tasks - MoodleDocs

Cron - MoodleDocs

"ps aux" explicado

Cómo determinar la fecha de creación de un proceso en Linux


Tal vez pueda interesarte


Compartí este artículo