(ES)Solución a la sobrecarga de CPU de kworker

Un bug bien conocido de kworker es uno que lo pone a generar interrupciones a lo loco y sin motivo aparente. Y cuando empieza es difícil de parar, salvo si reinicias y rezas para que no empiece de nuevo. Resultado: proceso ocupando más del 30% del procesador, ordenador echando humo y desesperación instantánea. Pero acabo de descubrir una manera de solucionarlo de forma fácil e indolora. Dado que el problema es que el sistema genera un numero exageradísimo de interrupciones, primero tenemos que descubrir que módulo está actuando de forma errónea. Para ello ejecutamos lo siguiente:

grep . -r /sys/firmware/acpi/interrupts/

Lo cual nos dará una salida parecida a esta (pero con más líneas): Captura de pantalla de 2013-05-13 20:08:43 Aquí buscamos la línea con más interrupciones generadas. Si kworker está loco, una línea mostrará un número mucho más grande que el resto. Apuntamos que “gpe” es el que las genera. En este caso el 1B Ahora, para pararlo ejecutamos:

echo disable > /sys/firmware/acpi/interrupts/gpeXX

Cambiando XX por el que nos corresponda. Ahora hacemos un top y, efectivamente, todo ha vuelto a la normalidad. El problema? Cuando te vuelva a pasar, no te vas a acordar de esto. La solución? Un bonito script que os he preparado:

#!/bin/bash

#Programado de la forma menos chapucera posible por: http://023.es
#EJECUTAR COMO ROOT O NO FUNCIONARÁ

#Genera una lista para ver que gpe falla
grep . -r /sys/firmware/acpi/interrupts/ > lista

#Guarda en la variable $gpe la dirección completa del gpe erróneo
num=$(cat lista | egrep -o '[0-9]+ ' | sort -r -n | head -n1)
#linea=$(cat lista | egrep -n "/sys/firmware/acpi/interrupts/gpe[A-Z,0-9]+:[ ]+$num" | cut -d":" -f1)
#ACUALIZACION: Como bien dice Aleix, el comando anterior puede fallar en caso de que haya muchas interrupciones. Esto se soluciona añadiendo el asterisco, tal y como se muestra aquí:
linea=$(cat lista | egrep -n “/sys/firmware/acpi/interrupts/gpe[A-Z,0-9]+:[ ]*+$num” | cut -d”:” -f1)
gpe=$(cat lista | head -n $linea | tail -n 1 | cut -d":" -f1)

#Manda señal de desactivación
echo "disable" > $gpe

rm lista

Ahora, os podéis crear un alias en vuestro .bashrc del estilo:

alias antikworker='sudo /carpeta/donde/esta/el/script/antikworker.sh

o

alias pudretekworker='sudo /carpeta/donde/esta/el/script/pudretekworker.sh

Cuando te pase este problema, solo llamas al script y solucionado! :D Otra opción sería tener una entrada en tu crontab a un script que comprobara cada cierto tiempo la carga del ordenador y, si supera un cierto límite, llamara al script de arriba. El límite es vuestra imaginación X) Espero que os sea útil. Hasta otra! Edit: Lee los comentarios que contienen información más depurada ;)

Comments

Lucas Traverso: Muchas gracias hace bastante que este problema me estuvo molestando. La “”solución”” que encontré fue rebootear cuando aparecía el bug y después no molestaba hasta que apagaba y prendía completamente la computadora. Deberías postear esto en algún foro oficial de Ubuntu (o linux, no se si esto es tema del kernel o de Ubuntu).

admin: Hola Lucas, me alegro de que te haya sido util. Después de escribir la entrada me fijé en que el módulo que falla es siempre el mismo (en mi caso el gpe1B) así que no hace falta que el script busque cual es cada vez que le pasa. Basta con un alias parecido a este: alias kw=’su -c “echo disable > /sys/firmware/acpi/interrupts/gpeXX”‘ Gracias por tu visita, espero verte más por aquí ;)

ole: Hola que tal, un gusto poder encontrar informacion sobre este tema en español. Quisieras consultarte algo. cuando trato de detenerlo con: “ echo disable > /sys/firmware/acpi/interrupts/gpeXX “ me sale esto: “ bash: /sys/firmware/acpi/interrupts/gpexx: Permiso denegado “ algunas solucion porque en mi caso cuando ejecuto “top” me sale 30% de uso del cpu en el proceso kworker. Gracias de antemano. Saludos.

admin: Hola, gracias por el comentario. Tienes que ejecutar el comando así: su -c “echo disable > /sys/firmware/acpi/interrupts/gpeXX” y recuerda cambiar las XX por el número que corresponda en tu caso. Coméntame si funciona ;)

ole: Hola. Utilice como me dijiste el comando: su -c echo disable > /sys/firmware/acpi/interrupts/gpe18 (18 porque es el gpe18 el que quiero detener) pero me sigue saliendo: bash: /sys/firmware/acpi/interrupts/gpe18: Permiso denegado No sé que hacer, estoy trabajando con Elementary os luna y me gusta mucho, pero en esta distro y en ubuntu me pasa lo mismo. Gracias.

admin: Hola, puedes probar a entrar como su primero, introducir la contraseña y luego lanzar el comando?? Si no te deja, no me cuadra…

ole: me sale “fallo en autentificacion” cuando entro primero con su :( . Que estará mal?

ole: Entre con “sudo su” ejecute para detenerlo y me sale: “id desconocido: disable” Pero sigue consumiendo el cpu, kworker sigue consumiendo 30%. Que hecho mal.

admin: Pues no se cual puede ser el fallo… Puede ser que tu kworker esté fallando por otro motivo distinto :S

Aleix: Hola, el script funciona muy bien, pero hay un caso en que falla: si Kworker tiene bastantes más interrupciones(por ejemplo 524297981), desaparece la separación de espacios entre la ruta del “gpe” y el número de interrupciones: 7:/sys/firmware/acpi/interrupts/gpe06:524297981 enabled Para solucionar-lo, solo hace falta cambiar esta linea: linea=$(cat lista | egrep -n “/sys/firmware/acpi/interrupts/gpe[A-Z,0-9]+:[ ]+$num” | cut -d”:” -f1) Por esta otra(solo añade el carácter ““): linea=$(cat lista | egrep -n “/sys/firmware/acpi/interrupts/gpe[A-Z,0-9]+:[ ]+$num” | cut -d”:” -f1) Felicidades por el blog, lo acabo de descubrir y me parece muy interesante, Saludos.

admin: Hola Aleix, muchas gracias por el comentario. En mi caso nunca dio tantas como para que fallara de ese modo, pero lo modifico ahora mismo. Muchas gracias por los cumplidos, espero verte más por aquí ;)

Daniel Serano: Hola, como estan, He visto su blog, pero en mi caso tengo un smartphone HTC Sensation y me aparecio este mismo programa o no se que… la verdad no soy ingeniero y no tengo idea de esto. Me pueden ayudar, que debo hacer, no se como hacer para que el movil funcione como estaba originalmente, como hago para no perder mis datos. Gracias, Daniel

admin: Hola Daniel, esta solución está pensada para sistemas Linux; Aunque Android está basado en Linux, el problema que tiene es otro, esta solución no valdría, lo siento

Yheison Gamba: Admin, a partir de hoy eres mi nuevo heroe, jejejeje He tenido este problema hace ya algun tiempo y me tenia loco, habia investigado por todas partes y no encontre ninguna solucion hasta que he encontrado la tuya, Muchas Gracias de verdad.

admin: Jajaja, de nada hombre, para eso estamos. La verdad es que este error hace tiempo que no me lo daba, supongo que será problema de las actualizaciones… Un saludo y gracias por tu comentario ;)

sam: hola, bueno me funciono, pero tuve que hacer lo siguiente ya que las otras no me sirvieron, tuve que ir directamente al directorio del gpe que estaba dando problemas y ejecutar el echo disable directo w3asel@compaq:/sys/firmware/acpi/interrupts$ sudo su root@compaq:/sys/firmware/acpi/interrupts# echo disable > gpe18 root@compaq:/sys/firmware/acpi/interrupts# asi me funciono

alej: Muy bueno. Una observación. Si corres el script salen los mensajes de error: usuario@usuario:~$ sudo ./kworker.sh cut: el delimitador debe ser un sólo carácter Pruebe «cut –help» para más información. egrep: La expresión regular es errónea head: la opción requiere un argumento – ‘n’ Pruebe «head –help» para más información. ./kworker.sh: línea 17: $gpe: redireccionamiento ambiguo Esta corrección adicionada linea=$(cat lista | egrep -n “/sys/firmware/acpi/interrupts/gpe[A-Z,0-9]+:[ ]+$num” | cut -d”:” -f1) tiene las comillas dobles mal. debe ser linea=$(cat lista | egrep -n “/sys/firmware/acpi/interrupts/gpe[A-Z,0-9]+:[ ]+$num” | cut -d”:” -f1) Gracias. exitos

GIOVANNI: ok, es oficial, y ni te conozco pero… TE AMO!!! Hace mas de un año que busco la solución T_T TE AMO!!! Muchas gracias!! :D

GIOVANNI: Ah, me olvidaba, en mi caso el que fallaba era el 06…el 1B era un poco alto pero no tanto como el 06. Saludos

maravento: Muy buena solución. Aquí te dejo tu script con las comillas arregladas Es necesario aclarar que no siempre cierra los procesos 100% y a veces hay que verificar y cerrarlos manualmente, sin embargo es un gran aporte a la comunidad. Felicitaciones. https://app.box.com/s/cn7rwzusk8om27zvzco5

Francis: Hola, no sé como crear un script, y no entiendo muy bien lo que hay que incluír en el. Tengo el problema con kworker el gpe06 específicamente. Agradecería mucho que alguien me explicara más detalladamente lo del script, ojalá con el parámetro gpe06 incluído, si es posible, lo agradecería mucho.

admin: Hola Francis. No hace falta el script puesto que el gpe que falla es siempre el mismo. Basta con añadir a tu .bashrc un alias parecido a: Alias nokw=’echo disable > /sys/firmware/acpi/interrupts/gpe06’ Cada vez que se le vaya el pistón ejecutas nokw y listo. No recuerdo si tenias que ser administrador o no. Un saludo y gracias por el coment

admin: Jajajaja Me alegro de que te sirviese!

admin: Muchas gracias maravento, pero el script no está subido actualmente, no?

maravento: Hola. Hemos retirado el script momentáneamente debido a que cuando se corre, mas de una vez, genera error (tanto el tuyo como el nuestro) Y no siempre el gpe06 es el que se “dispara”. Depende del sistema operativo, la versión, el hardware… En las pruebas que hicimos en varios entornos, hemos detectado que esto varía. La idea del script (que no la hemos todavía cuajado) es determinar cual es el valor máximo aproximado que puede manejar un gpe. El script lo que hará es supervisar estos valores, y si el proceso supera este valor lo reinicia o setea a 0. Deshabilitarlo completamente no es bueno ya que es un proceso necesario para el sistema. Solo hay que “controlarlo” Gracias por tu aporte

admin: Me refiero a que una vez que a ti te ha fallado uno, el 1C por ejemplo , la próxima vez te va a fallar ese.

maravento: mmm. interesante. No lo sabía. Gracias por el dato jodido ese kworker. Tengo que investigar un poco mas para poder cubrir todos los escenarios posibles este asunto afecta de manera indirecta un bug muy antiguo de ubuntu relacionado con la suspensión e hibernación en las laptops (no reaccionan después de haber caído en suspensión). Tal vez kworker sea una de las causas. Una vez tenga algo concreto te notifico

maravento: Hola admin. Hemos publicado un post basados en tu script de kworker, ya que este problema afecta la hibernación y/o suspensión en Ubuntu (algo que veníamos tratando desde hace algún tiempo), por tanto es de vital importancia, porque están directamente relacionados. Gracias por tu gran trabajo http://www.maravento.com/2015/01/kworker.html

admin: Muchas gracias por difundirlo, me alegro que sea de utilidad. Luego le hecho un ojo a los cambios que le habéis introducido a ver si mejoro mi versión.

maravento: los cambios que pensabamos hacer, finalmente no lo hicimos porque daba error en algunos entornos. Por tanto quedo tal cual tu publicación. gracias nuevamente

Francisco Sánchez: Voy a comentar como introducir el script o uno personalizado en systemd para que se inicie solo al comenzar la sesión y no tener que teclear nada. Es muy util si usas arclinux como yo y estás obligado a systemd. Llevo 2 dóas investigando y por fin lo he conseguido. Es difícil porque la documentación es escasa. Primero hay que guardar el script en un lugar que consideréis oportuno y darle permisos de programa ejecutable. Yo personalmente lo he guardado en: /usr/lib/systemd/scripts/kworkerGPE6F.sh (lo he llamado así porque en mi equipo el gpe que causa el bug es el GPE6f) Mi script es mucho mas sencillo porque una vez localizada la falla no es necesario cargar el script completo: #Manda señal de desactivación echo “disable” > /sys/firmware/acpi/interrupts/gpe6F Después viene lo complicado entre comillas, porque realmente es muy sencillo, lo dificil ha sido llegar a crearlo bien. Hay que crear un servicio para systemd que llame al script y lo ejecute en el momento adecuado, o sea, después de iniciado kworker y nunca antes pues si comienza antes no funcionará. Yo he creado un archivo de texto plano al que he llamado kworkerGPE6.service y lo he guardado en /usr/lib/systemd/system/ el contenido del archivo es: [Unit] Requires=multi-user.target Wants=display-manager.service Conflicts=rescue.service rescue.target After=multi-user.target rescue.service rescue.target display-manager.service systemd-user-sessions.service [Service] ExecStart=/bin/sh -c /lib/systemd/scripts/kworkerGPE6F.sh Group=users [Install] WantedBy=multi-user.target Después de editar guardamos. Yo he dado permisos tanto al script como al servicio al grupo users (me refiero a los archivos) Finalmente con todo esto hecho vamos a una terminal y tecleamos sudo systemctl enable kworkerGPE6F.service reiniciamos y si todo está bien hecho problema solucionado. No soy informático, seguramente esto es mejorable y solo es unejemplo al que me ha costado mucho llegar. Espero que le sirva a alguien. Recordad que hay que cambiar GPE6F por el que a vosotros os de problemas y que este metódo funciona en archlinux, no se como trabaja systemd en otras distribuciones. Saludos.

admin: Muchas gracias por compartir tus descubrimientos Francisco, es buena idea lo de iniciarlo como servicio para olvidarte del problema ya para siempre. Sin embargo, como ya sabemos que no hay que esperar a que las interrupciones se disparen para saber que GPE desactivar (siempre es el mismo) se podría simplemente añadir una entrada en el cron para que se ejecute el script en cada reboot, no? Yo últimamente no estoy teniendo este problema, por lo que no puedo probarlo, pero viendo la cantidad de visitas que tiene esta entrada a diario está claro que el problema está más extendido de lo que parece.

Francisco Sánchez: Tienes razón con introducir en cron el script, pero el gran problema de sistemas como archlinux con plena integración de systemd es que cron no trabaja como en sysvinit y que además la tendencia va hacia la sustitución de cron por los timer de systemd, razón por la cual al final es mas coherente mirar hacia systemd, aunque sea mas desconocido y poco a poco desechar otro tipo de soluciones. Incluso intenté activar mediante systemd el antiguo /etc/rc.local, pero generaba tantos problemas que me di cuenta de que la solución mas coherente pasaba por coger el toro por lis cuernos con lo disponible a este momento en archlinux y no hacer involuciones condicionadas que con el tiempo, a medio plazo seguro que quedan obsoletas.

David.: Hola admin. Llego tarde a tu post porque las he pasado mal con un notebook Aspire One (Atom con GMA 3500) corriendo Debian. Me salían interrupciones por un problema en cpu0 (esto tiene 4 núcleos). Mi solución fue cambiar el kernel 3.16 que trae por el 4.0.4 de los backports. Mano de santo. Peor ahora tengo la duda si con tu solución hubiera sido suficiente. Un saludo :)

admin: Viste si era el comando kworker el que fallaba?

Francisco Sánchez: Tengo que hacer un apunte acerca del serivcio kworker en cuestión, después de un tiempo volviendome loco con steam y otros juego pensando que tenía mal instalado el driver nvidia o el de sonido de pulseaudio, he descubierto que si se paraliza este servicio de interrupciones programadas de la cpu los juego congelan el ordenador. Lo descubrí al hacer una instalación paralela de ubuntu con archlinux qe ya tengo instalado ara descartar que no fuera problema del hardware. Funcionaba todo perfecto hasta que decidí parar kworker en ubuntu pues me daba el problema de consumo de cpu. Fue parar el servicio y congelar de nuevo el pc con los juegos que usan opengl. Lo digo para que nadie se vuelva loco buscando solución si le sucede algo similar.

erm3nda: Si buscas que módulo falla y resulta ser algo fácil de cambiar (ejemplo tarjeta ethernet) y la reemplazas mucho mejor que si pudretekworker cada vez que enciendas :-)

Article automatically imported from my old wordpress blog. Here only for reference. Possible format errors and probable missing images. Sorry about that.

  • Previous post
  • Next post