En un programa de Julia que se ejecuta en Linux, necesito iniciar una acción dedicada cuando se cambia el tamaño de una ventana de consola. Entonces, ¿cómo en Julia, puedo interceptar la señal del sistema SIGWINCH (cambio de tamaño de ventana) y asignarle una función que realice la acción requerida?
En Ada es bastante sencillo declararlo:
protected Signalhandler is
procedure Handlewindowresizing;
pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
end Signalhandler;
SOLUCIÓN TENTATIVA BASADA EN LA IDEA DEL ESQUEMERO: Intento usar una Biblioteca C que realiza el monitoreo de interrupción SIGWINCH.
myLibrary.h
void Winresize (void Sig_Handler());
myLibrary.c
#include "myLibrary.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void Winresize(void sig_handler (void)) {
signal(SIGWINCH, sig_handler);
}
Recopilación y preparación de la biblioteca.
gcc -c -Wall -fPIC myLibrary.c
gcc -shared -fPIC -o myLibrary.so myLibrary.o
Programa en Julia que usa la Biblioteca C:
function getc1()
ret = ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), stdin.handle, true)
ret == 0 || error("unable to switch to raw mode")
c = read(stdin, UInt8)
ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), stdin.handle, false)
c
end
function traitement() println(displaysize(stdout)); end
Mon_traitement_c = @cfunction(traitement, Cvoid, ())
ccall((:Winresize, "/home/Emile/programmation/Julia/myLibrary.so"), Cvoid, (Ptr{Cvoid},), Mon_traitement_c)
while true
println(getc1())
end
El programa Julia se ejecuta correctamente, pero cuando se cambia el tamaño de la ventana del terminal, se emite un fallo de segmentación (núcleo volcado) y se dice que el programa salió con el código: 139.
Entonces, la pregunta es ¿de dónde viene esta falla de segmentación? ¿Del modelo de compilación? ¿Julia no tiene derecho a controlar la ejecución del código en la parte de memoria donde C gestiona la supervisión de la señal?
Eliminar la operación println en Sig_handler suprime el error de segmentación:
curr_size = displaysize(stdout)
new_size = curr_size
function traitement() global new_size ; new_size = displaysize(stdout); return end
Mon_traitement_c = @cfunction(traitement, Cvoid, ())
ccall((:Winresize, "/home/Emile/programmation/Julia/myLibrary.so"), Cvoid, (Ptr{Cvoid},), Mon_traitement_c)
while true
global curr_size, new_size
if new_size != curr_size
curr_size = new_size
println(curr_size)
end
sleep(0.1)
end