Emile
Emile

Reputation: 163

System signal interception in Julia

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  

Upvotes: 10

Views: 460

Answers (2)

Schemer
Schemer

Reputation: 11

Yes, it is indeed a fallback solution which is hardly what one expects from a new language full of promises ... but for lack of thrushes we can actually eat blackbirds (smile).

But if Julia hasn't planned to be able to take into account the system signals of the Unix/Linux world, it might be possible to do it using a C library like the one that signal.h accesses.

 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>

 void sig_handler(int signum)
 {
    printf("Received signal %d\n", signum);
 }

int main()
{
   signal(SIGINT, sig_handler);
   sleep(10); // This is your chance to press CTRL-C
   return 0;
}

We would have to define a julia function doing what is expected when the system signal is received. Make it usable in C as Sig_handler and call from julia the C statement signal(SIGWINCH, Sig_handler);

I am not enough familiar with julia to write the exact code. But this is the idea...

Upvotes: 1

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

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!.

Upvotes: 4

Related Questions