Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System signal interception in Julia

Tags:

signals

julia

ada

In a Julia program which run under Linux, I need to launch a dedicated action when a console window is resized. So how in Julia, can I intercept the system signal SIGWINCH (window resizing) and attach to it a function which performs the required action ?

In Ada it is rather straightforward to declare it :

 protected Signalhandler is
      procedure Handlewindowresizing;
      pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
 end Signalhandler;

TENTATIVE SOLUTION BASED ON IDEA OF SCHEMER : I try to use a C Library which conducts the SIGWINCH interruption monitoring.

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);
}

Compilation & Library preparation

gcc -c -Wall -fPIC myLibrary.c

gcc -shared -fPIC -o myLibrary.so myLibrary.o

Program in Julia which uses the C-Library :

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 

The Julia program run properly but when the terminal window is resized a Segmentation fault (core dumped) is issued and program is said exited with code: 139.

So the question is where does this segmentation fault come from ? From the compilation model ? Julia has not the right to control code execution in the memory part where C manages the signal monitoring ?

Removing println operation in Sig_handler suppress the segmentation fault :

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  
like image 915
Emile Avatar asked Mar 22 '20 23:03

Emile


1 Answers

Since no one has answered this question so far, one possible workaround could be asynchronously monitoring the size of the terminal in some time intervals.

function monitor_term(func)
    @async begin 
        curr_size = displaysize(stdout)
        while (true)
            sleep(0.1)
            new_size = displaysize(stdout)
            if new_size != curr_size
                curr_size = new_size
                func()
            end
        end
    end
end

And now sample usage:

julia> monitor_term(() -> print("BOO!"))
Task (runnable) @0x0000000013071710

As long as the terminal is alive, any change to its size will print BOO!.

like image 192
Przemyslaw Szufel Avatar answered Sep 18 '22 20:09

Przemyslaw Szufel