Системний перехоплення сигналу в Джулії


9

У програмі Julia, яка працює під Linux, мені потрібно запустити спеціальну дію, коли змінено вікно консолі. Так як у Julia, чи можу я перехопити системний сигнал SIGWINCH (зміна розміру вікна) і приєднати до нього функцію, яка виконує необхідну дію?

В Ada досить просто заявити про це:

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

ТЕНТАТИВНЕ РІШЕННЯ НА ОСНОВІ ІДЕЇ ШЕМЕРУ: Я намагаюся використовувати С-бібліотеку, яка проводить моніторинг переривань 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

Програма в Джулії, яка використовує С-бібліотеку:

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.

Тож питання полягає в тому, звідки береться ця помилка сегментації? З моделі компіляції? Юлія не має права контролювати виконання коду в частині пам'яті, де С керує моніторингом сигналу?

Видалення операції 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  

1
Це слід досить просто реалізувати як модуль SignalHandlers.jl, використовуючи ccall ((: сигнал ...) та @cfunction, але AFAIK цього не було зроблено.
Білл

Ваша пропозиція була вдалою. Дякую.
Еміль

Відповіді:


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

А тепер вибіркове використання:

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

Поки термінал живий, будь-яка зміна його розміру буде надрукована BOO!.


Я не знав цього приємного способу отримати поточний розмір вікна консолі. displayize (stdout) Дякую
Еміль

0

Так, це дійсно резервне рішення, що навряд чи можна очікувати від нової мови, повної обіцянок ... але за відсутності дроздень насправді ми можемо поїсти чорних птахів (посмішка).

Але якщо Юлія не планувала мати можливість враховувати системні сигнали світу Unix / Linux, можливо, це можливо зробити, використовуючи бібліотеку C, подібну до тієї, яка має доступ до сигналу.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 та зателефонувати з julia на сигнал твердження C (SIGWINCH, Sig_handler);

Мені недостатньо знайома Юлія, щоб написати точний код. Але це ідея ...


Я спробую реалізувати те, що ви пропонуєте.
Еміль

@Emile, якщо вам вдасться реалізувати його (включаючи написання Джулії ccal), і хочете згодом перетворити його в стандартний пакет Julia, я можу допомогти з цим упаковкою.
Перемислав Шуфель

Належним чином відзначено ! Я повинен трохи далі в документації на Джулію.
Еміль

@Przemyslaw Szufel: Який аналіз розгляду сегментації, показаний вище, є доповненням до мого запитання і виникає, коли функція C використовується для вибору переривання?
Еміль

Я не писав код інтеграції Julia-C. Однак я знаю, що протягом тривалого часу виникала помилка сегментації, коли будь-яка системна введення використовувалася в потоках Джулії, тому, ймовірно, там є деякі проблеми. Можливо, на першому кроці спробуйте побачити, що відбувається, коли ви просто println ("boo"), не запитуючи розмір терміналу.
Перемислав Шуфель
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.