Система перехвата сигнала в Юлии - PullRequest
9 голосов
/ 23 марта 2020

В программе Julia, которая работает под Linux, мне нужно запустить специальное действие при изменении размера окна консоли. Итак, как в Джулии я могу перехватить системный сигнал SIGWINCH (изменение размера окна) и прикрепить к нему функцию, которая выполняет требуемое действие?

В Аде объявить его довольно просто:

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

TENTATIVE SOLUTION НА ОСНОВЕ ИДЕИ ШЕМЕРА: я пытаюсь использовать библиотеку 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);
}

Компиляция и подготовка библиотеки

g cc - c -Wall -fPI C myLibrary. c

g cc - shared -fPI C -o myLibrary.so myLibrary.o

Программа на Julia, использующая 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 

Программа Julia запускается правильно, но когда терминал размер окна изменяется. Выдается ошибка сегментации (сбрасывается ядро), и программа, как говорят, завершается с кодом: 139.

Итак, вопрос в том, откуда возникает эта ошибка сегментации? Из модели компиляции? Джулия не имеет права контролировать выполнение кода в той части памяти, где C управляет мониторингом сигнала?

Удаление операции println в Sig_handler подавляет ошибку сегментации:

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  

Ответы [ 2 ]

4 голосов
/ 23 марта 2020

Поскольку до сих пор никто не ответил на этот вопрос, одним из возможных обходных путей может быть асинхронный мониторинг размера терминала в некоторых временных интервалах.

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!.

0 голосов
/ 24 марта 2020

Да, это действительно запасное решение, которое вряд ли можно ожидать от нового языка, полного обещаний ... но из-за отсутствия дроздов мы можем есть черных дроздов (улыбается).

Но если Джулия не планировал принимать во внимание системные сигналы мира Unix / Linux, возможно, это возможно сделать с помощью библиотеки C, подобной той, к которой обращается signal.h.

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

Мы должны были бы определить функцию julia, выполняющую то, что ожидается при получении системного сигнала. Сделайте его пригодным для использования в C как Sig_handler и вызовите от Джулии сигнал оператора C (SIGWINCH, Sig_handler);

Я недостаточно знаком с Юлией, чтобы написать точный код. Но это идея ...

...