茱莉亚的系统信号拦截



在Linux下运行的Julia程序中,当控制台窗口调整大小时,我需要启动一个专用操作。那么,在Julia中,我如何拦截系统信号SIGWINCH(窗口大小调整(并为其附加一个执行所需操作的函数呢?

在Ada中,声明它相当简单:

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

基于SCHEMER思想的初步解决方案:我尝试使用一个C库来进行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);
}

编译&图书馆准备

gcc-c-Wall-fPIC myLibrary.c

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

使用C-Library的Julia程序:

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 

Julia程序运行正常,但当调整终端窗口的大小时,会发出分段故障(核心转储(,并表示程序已退出,代码为:139。

那么问题来了,这个分割错误是从哪里来的呢?从编译模型?Julia无权控制C管理信号监控的内存部分中的代码执行?

删除Sig_handler中的println操作可抑制分段故障:

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  

由于到目前为止还没有人回答这个问题,一种可能的解决方法是在某些时间间隔内异步监控终端的大小。

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

现在示例用法:

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

只要终端处于活动状态,对其大小的任何更改都将打印BOO!

是的,它确实是一个后备解决方案,这很难满足人们对充满承诺的新语言的期望。。。但由于缺少画眉,我们实际上可以吃黑鸟(微笑(。

但是,如果Julia没有计划能够考虑Unix/Linux世界的系统信号,那么可以使用像signal.h访问的C库这样的C库。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sig_handler(int signum)
{
printf("Received signal %dn", signum);
}
int main()
{
signal(SIGINT, sig_handler);
sleep(10); // This is your chance to press CTRL-C
return 0;
}

我们必须定义一个julia函数,在接收到系统信号时做预期的事情。使其在C中可用作Sig_handler,并从julia调用C语句信号(SIGWINCH,Sig_handle(;

我对julia不够熟悉,写不出确切的代码。但这是一个想法。。。

最新更新