Julia 中的系统信号拦截

Emi*_*ile 9 signals ada julia

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

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

 protected Signalhandler is
      procedure Handlewindowresizing;
      pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
 end Signalhandler;
Run Code Online (Sandbox Code Playgroud)

基于 SCHEMER 思想的暂定解决方案:我尝试使用 C 库进行 SIGWINCH 中断监视。

我的图书馆.h

void Winresize (void Sig_Handler());
Run Code Online (Sandbox Code Playgroud)

我的图书馆

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

void Winresize(void sig_handler (void)) { 
     signal(SIGWINCH, sig_handler);
}
Run Code Online (Sandbox Code Playgroud)

编译和库准备

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 
Run Code Online (Sandbox Code Playgroud)

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  
Run Code Online (Sandbox Code Playgroud)

Prz*_*fel 4

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

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
Run Code Online (Sandbox Code Playgroud)

现在示例用法:

julia> monitor_term(() -> print("BOO!"))
Task (runnable) @0x0000000013071710
Run Code Online (Sandbox Code Playgroud)

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