Reputation: 163
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
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
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