Escritos · Congelamientos de la plataforma
Una acción de lectura no cancelable en el propio ejecutor de pruebas de IntelliJ — y cómo se corrigió
Una tarea en segundo plano envolvía la mitad de su trabajo en una acción de lectura cancelable y la otra mitad en una bloqueante, sin ninguna comprobación de cancelación entre ambas. Es un patrón de manual de congelamiento de la interfaz, y estaba en el propio ejecutor de pruebas de IntelliJ.
Qué estaba buscando
Uno de los plugins de mi catálogo, Background ReadAction Freeze Companion, es una comprobación estática para un error concreto: una acción de lectura bloqueante en un hilo en segundo plano sin checkCanceled(). El propio Platform Blog de JetBrains señala ese patrón como una causa recurrente de congelamientos de la interfaz, porque una acción de escritura pendiente — tú escribiendo en el editor — tiene que esperar a que la acción de lectura termine. Corrí la misma comprobación como un escaneo sobre el propio master de IntelliJ Community.
Qué encontró
SearchForTestsTask es un Task.Backgroundable. Su run() envolvía search() en un ReadAction.nonBlocking() cancelable — la llamada correcta — y luego, unas líneas más abajo, llamaba al onFound() hermano a través de un ReadAction.run() bloqueante, sin ningún checkCanceled() en toda la clase. Así que la mitad de la tarea se podía cancelar y la otra mitad no.
Lo reporté como IDEA-393501 (originalmente IJPL-254654). JetBrains lo movió al proyecto IDEA, bajo Java › Tests, y se lo asignó a un desarrollador.
La parte que lo hizo más difícil de lo que parecía
Un arreglo tosco — cambiar la llamada bloqueante por una acción de lectura no bloqueante — habría introducido otro error. Una acción de lectura no bloqueante se puede reiniciar, y onFound() escribe archivos; en un reinicio los escribiría dos veces. En un comentario de seguimiento añadí dos puntos: que la rama por defecto en modo inteligente también bloqueaba, a través del obsoleto DumbService.runReadActionInSmartMode() (que usa ReadAction.computeBlocking() internamente), y que el arreglo real tenía que mantener segura la parte de escritura.
Cómo lo corrigió JetBrains
El 28 de octubre de 2026, el arreglo llegó a master (commit 4a88fdfa): onFound() ahora se ejecuta en una acción de lectura no bloqueante en modo inteligente, los bucles que construyen las listas de pruebas llaman a checkCanceled(), y el paso de subida de JUnit se movió a onSuccess(). El ticket está marcado como Fixed.
Por qué escribo esto
Esta es toda la idea de Gap Hunter Labs en un solo ticket: un error real, en código del que mucha gente depende, encontrado por una comprobación que te puedo señalar, reportado con suficiente análisis para ser accionable, y corregido por las personas que son dueñas del código. El conjunto completo de tickets de plataforma está en Ingeniería y evidencia.