Sistem intersepsi sinyal di Julia

9

Dalam program Julia yang berjalan di Linux, saya harus meluncurkan tindakan khusus ketika jendela konsol diubah ukurannya. Jadi bagaimana di Julia, dapatkah saya mencegat sinyal sistem SIGWINCH (mengubah ukuran jendela) dan melampirkan padanya sebuah fungsi yang melakukan tindakan yang diperlukan?

Dalam Ada agak mudah untuk menyatakannya:

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

SOLUSI TENTATIF BERDASARKAN IDEA OF SCHEMER: Saya mencoba menggunakan Perpustakaan C yang melakukan pemantauan gangguan 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);
}

Kompilasi & persiapan Perpustakaan

gcc -c -Wall -fPIC myLibrary.c

gcc -bagi -fPIC -o myLibrary.so myLibrary.o

Program di Julia yang menggunakan 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 

Program Julia berjalan dengan baik tetapi ketika jendela terminal diubah ukurannya kesalahan Segmentasi (core dumped) dikeluarkan dan program dikatakan keluar dengan kode: 139.

Jadi pertanyaannya adalah dari mana kesalahan segmentasi ini berasal? Dari model kompilasi? Julia tidak memiliki hak untuk mengontrol eksekusi kode di bagian memori di mana C mengelola pemantauan sinyal?

Menghapus operasi println di Sig_handler menekan kesalahan segmentasi:

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  
Emile
sumber
1
Seharusnya cukup mudah untuk mengaktualisasikan ini sebagai modul SignalHandlers.jl menggunakan ccall ((: sinyal ...) dan fungsi @, tetapi AFAIK ini belum dilakukan.
Bill
Saran Anda bagus. Terima kasih.
Emile

Jawaban:

4

Karena tidak ada yang menjawab pertanyaan ini sejauh ini, satu solusi yang mungkin dapat secara asinkron memantau ukuran terminal dalam beberapa interval waktu.

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

Dan sekarang penggunaan sampel:

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

Selama terminal masih hidup, setiap perubahan ukurannya akan dicetak BOO!.

Przemyslaw Szufel
sumber
Saya tidak tahu cara yang baik untuk mendapatkan ukuran jendela konsol saat ini. displaysize (stdout) Terima kasih
Emile
0

Ya, itu memang solusi mundur yang hampir tidak seperti yang diharapkan seseorang dari bahasa baru yang penuh janji ... tapi karena kekurangan sariawan kita sebenarnya bisa makan burung hitam (senyum).

Tetapi jika Julia belum berencana untuk memperhitungkan sinyal sistem dari dunia Unix / Linux, mungkin dimungkinkan untuk melakukannya dengan menggunakan pustaka C seperti yang diakses oleh 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;
}

Kita harus mendefinisikan fungsi julia melakukan apa yang diharapkan ketika sinyal sistem diterima. Jadikan itu bisa digunakan dalam C sebagai Sig_handler dan panggil dari julia sinyal pernyataan C (SIGWINCH, Sig_handler);

Saya tidak cukup akrab dengan julia untuk menulis kode yang tepat. Tapi ini idenya ...

Pengatur siasat
sumber
Saya akan mencoba menerapkan apa yang Anda usulkan.
Emile
@Emile jika Anda berhasil mengimplementasikannya (termasuk menulis Jullia ccal) dan ingin kemudian membuatnya menjadi paket standar Julia, saya dapat membantu mengemasnya.
Przemyslaw Szufel
Sepatutnya dicatat ! Saya harus sedikit lebih jauh dalam dokumentasi julia.
Emile
@ Przemyslaw Szufel: Apa analisis Anda tentang kesalahan segmentasi yang ditunjukkan di atas sebagai pelengkap pertanyaan saya dan muncul ketika fungsi C digunakan untuk menangkap interupsi?
Emile
Saya belum menulis kode integrasi Julia-C. Namun, saya tahu bahwa untuk waktu yang sangat lama ada kesalahan segfault setiap kali sistem IO digunakan dalam utas Julia jadi mungkin ada beberapa masalah di sana. Mungkin pada langkah pertama cobalah untuk melihat apa yang terjadi ketika Anda baru saja mencetak ("boo") tanpa meminta ukuran terminal.
Przemyslaw Szufel