【发布时间】:2020-07-03 11:28:37
【问题描述】:
在 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 库的 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
【问题讨论】:
-
使用 ccall((:signal...) 和 @cfunction 将其实现为 SignalHandlers.jl 模块应该相当简单,但 AFAIK 这还没有完成。
-
您的建议很好。谢谢。