ジュリアでのシステム信号傍受


9

Linuxで動作するJuliaプログラムでは、コンソールウィンドウのサイズが変更されたときに専用のアクションを起動する必要があります。では、ジュリアでは、システム信号SIGWINCH(ウィンドウのサイズ変更)をインターセプトして、必要なアクションを実行する関数をそれにアタッチできますか?

Adaでは、それを宣言するのはかなり簡単です。

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

SCHEMERのアイデアに基づく暫定的な解決策:SIGWINCH割り込み監視を実行するCライブラリを使用しようとします。

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  

1
これが行われていない信号...)と@cfunctionが、私の知る限り:ccallを((使用SignalHandlers.jlモジュールとしてこれを実現するためには非常に簡単でなければなりません。
ビル・

あなたの提案は良いものでした。ありがとうございました。
エミール

回答:


4

これまで誰もこの質問に答えていないので、1つの可能な回避策は、いくつかの時間間隔で端末のサイズを非同期に監視することです。

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!


現在のコンソールウィンドウサイズを取得するこの素晴らしい方法を知りませんでした。displaysize(stdout)ありがとう
Emile

0

はい、それは確かに、約束に満ちた新しい言語から期待することはほとんどないフォールバックソリューションです...しかし、ツグミの欠如のために、私たちは実際にクロドリを食べることができます(笑)。

しかし、JuliaがUnix / Linuxの世界のシステムシグナルを考慮に入れることを計画していない場合は、signal.hがアクセスするようなCライブラリを使用してそれを行うことが可能かもしれません。

 #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;
}

システム信号を受信したときに期待されることを行うジュリア関数を定義する必要があります。CでSig_handlerとして使用できるようにし、JuliaからCステートメントsignal(SIGWINCH、Sig_handler);を呼び出します。

正確なコードを書くには、juliaに慣れていません。しかし、これはアイデアです...


私はあなたが提案したものを実装しようとします。
エミール

@Emile(Julliaの記述を含む)を実装してccal、後で標準のJuliaパッケージにしたい場合は、パッケージ化のお手伝いをします。
Przemyslaw Szufel

きちんと注意!juliaのドキュメントでもう少し詳しく説明する必要があります。
エミール

@Przemyslaw Szufel:上記のセグメンテーション違反の分析は私の質問を補足するもので、C関数を使用して割り込みをキャッチしたときに発生しますか?
エミール

Julia-C統合コードは作成していません。ただし、JuliaスレッドでシステムIOが使用されると、segfaultエラーが非常に長い間発生したため、おそらくそこにいくつかの問題があることを私は知っています。たぶん最初のステップで、端末のサイズを尋ねずにprintln( "boo")を実行したときに何が起こったかを確認してみてください。
Przemyslaw Szufel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.