Julia'da sistem sinyali yakalaması


9

Linux altında çalışan bir Julia programında, bir konsol penceresi yeniden boyutlandırıldığında özel bir eylem başlatmam gerekiyor. Peki Julia'da SIGWINCH (pencere yeniden boyutlandırma) sistem sinyalini nasıl kesebilir ve ona gerekli eylemi gerçekleştiren bir işlev ekleyebilir miyim?

Ada'da beyan etmek oldukça basittir:

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

SCHEMER FİKİRİNE DAYALI ÇADIRLI ÇÖZÜM: SIGWINCH kesinti izlemesini yürüten bir C Kütüphanesi kullanmaya çalışıyorum.

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

Derleme ve Kütüphane Hazırlığı

gcc -c -Duvar -fPIC myLibrary.c

gcc -shared -fPIC -o myLibrary.so myLibrary.o

Julia'da C Kütüphanesini kullanan program:

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 programı düzgün çalışıyor, ancak terminal penceresi yeniden boyutlandırıldığında bir Segmentasyon hatası (çekirdek dökümü) yayınlanıyor ve program kod: 139 ile çıkarıldı.

Soru şu; bu segmentasyon hatası nereden geliyor? Derleme modelinden mi? Julia'nın C'nin sinyal izlemeyi yönettiği bellek bölümünde kod yürütülmesini kontrol etme hakkı yok mu?

Sig_handler'da println işleminin kaldırılması segmentasyon hatasını bastırır:

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
Bunu ccall ((: signal ...) ve @cfunction kullanarak bir SignalHandlers.jl modülü olarak gerçekleştirmek oldukça basit olmalı, ancak AFAIK bu yapılmadı.
Bill

Önerin güzeldi. Teşekkür ederim.
Emile

Yanıtlar:


4

Kimse bu soruyu şu ana kadar cevaplamadığından, olası bir geçici çözüm bazı zaman aralıklarında terminalin boyutunu eşzamansız olarak izlemek olabilir.

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

Ve şimdi örnek kullanımı:

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

Terminal canlı olduğu sürece, boyutunda herhangi bir değişiklik yazdırılır BOO!.


Mevcut konsol penceresi boyutunu almak için bu güzel yolu bilmiyordum. displaysize (stdout) Teşekkür ederim
Emile

0

Evet, gerçekten de vaatlerle dolu yeni bir dilden beklediğimiz bir geri dönüş çözümü ... ama pamukçukların olmaması için aslında karatavuk yiyebiliriz (gülümseme).

Ancak Julia, Unix / Linux dünyasının sistem sinyallerini dikkate almayı planlamamışsa, sinyal.h'nin eriştiği gibi bir C kütüphanesi kullanarak bunu yapmak mümkün olabilir.

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

Sistem sinyali alındığında bekleneni yapan bir julia işlevi tanımlamamız gerekir. C'de Sig_handler olarak kullanılabilir hale getirin ve Julia'dan C deyimi sinyalini (SIGWINCH, Sig_handler) arayın;

Tam kodu yazmak için Julia'ya aşina değilim. Ama fikir bu ...


Teklif ettiğin şeyi uygulamaya çalışacağım.
Emile

@Emile (Jullia'nın yazılması dahil) uygulamayı başarabilir ccalve daha sonra standart bir Julia paketine dönüştürürseniz, bunu paketlemede yardımcı olabilirim.
Przemyslaw Szufel

Usulüne uygun olarak not edildi! Julia belgelerinde biraz daha ilerlemeliyim.
Emile

@Przemyslaw Szufel: Yukarıda sorumun tamamlayıcısı olarak gösterilen ve kesintiyi yakalamak için C işlevi kullanıldığında ortaya çıkan segmentasyon hatası analiziniz nedir?
Emile

Julia-C entegrasyon kodunu yazmıyorum. Ancak, Julia iş parçacığında herhangi bir sistem IO kullanıldığında çok uzun bir süre bir segfault hatası olduğunu biliyorum, bu yüzden muhtemelen bazı sorunlar var. Belki ilk adımda sadece terminal boyutu sormadan println ("boo") ne olduğunu görmeye çalışın.
Przemyslaw Szufel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.