การสกัดกั้นสัญญาณของระบบใน Julia


9

ในโปรแกรม Julia ที่ทำงานภายใต้ Linux ฉันจำเป็นต้องเปิดใช้งานแอคชั่นเฉพาะเมื่อปรับขนาดหน้าต่างคอนโซล ดังนั้นใน Julia ฉันจะตัดสัญญาณของระบบ SIGWINCH (ปรับขนาดหน้าต่าง) และแนบไปกับฟังก์ชันที่ดำเนินการตามที่ต้องการได้อย่างไร

ใน Ada ค่อนข้างตรงไปตรงมาที่จะประกาศ:

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

แนวทางแก้ไขปัญหาเกี่ยวกับความคิดพื้นฐานของความคิด: ฉันพยายามใช้ห้องสมุด 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);
}

การรวบรวม & การเตรียมห้องสมุด

gcc -c -Wall -fPIC myLibrary.c

gcc -shared -fPIC -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 ทำงานได้อย่างถูกต้อง แต่เมื่อหน้าต่างเทอร์มินัลถูกปรับขนาดข้อผิดพลาดในการแบ่งส่วน (การถ่ายโอนข้อมูลหลัก) จะถูกใช้

ดังนั้นคำถามคือความผิดของการแบ่งส่วนนี้มาจากไหน? จากรูปแบบการรวบรวม? Julia ไม่มีสิทธิ์ในการควบคุมการใช้รหัสในส่วนของหน่วยความจำที่ 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  

1
มันควรจะตรงไปตรงมาพอสมควรที่จะทำให้เป็นจริงเป็นโมดูล SignalHandlers.jl โดยใช้ ccall ((: สัญญาณ ... ) และ @cfunction แต่ AFAIK ยังไม่ได้ทำ
Bill

คำแนะนำของคุณดีมาก ขอบคุณ.
Emile

คำตอบ:


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) ขอขอบคุณ
Emile

0

ใช่มันเป็นทางออกทางเลือกซึ่งแทบจะไม่ได้สิ่งที่เราคาดหวังจากภาษาใหม่ที่เต็มไปด้วยคำสัญญา ... แต่สำหรับการขาดดงเราสามารถกินนกเบิร์ด (ยิ้ม) จริง ๆ

แต่ถ้า Julia ไม่ได้วางแผนที่จะคำนึงถึงสัญญาณระบบของโลก Unix / Linux มันอาจเป็นไปได้ที่จะทำมันโดยใช้ C library เช่นเดียวกับที่ 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 และโทรจาก julia สัญญาณ C statement (SIGWINCH, Sig_handler);

ฉันไม่คุ้นเคยกับจูเลียในการเขียนรหัสที่แน่นอน แต่นี่เป็นความคิด ...


ฉันจะพยายามใช้สิ่งที่คุณเสนอ
Emile

@Emile ถ้าคุณจัดการที่จะใช้มัน (รวมถึงการเขียนของ Jullia ccal) และต้องการให้มันกลายเป็นแพ็คเกจ Julia มาตรฐานฉันสามารถช่วยในการบรรจุภัณฑ์ได้
Przemyslaw Szufel

บันทึกรับรองสำเนาถูกต้อง ! ฉันต้องเพิ่มเติมเล็กน้อยในเอกสารจูเลีย
Emile

@Pzemyslaw Szufel: การวิเคราะห์ความผิดพลาดในการแบ่งกลุ่มของคุณแสดงให้เห็นว่าเป็นส่วนเติมเต็มสำหรับคำถามของฉันและเกิดขึ้นเมื่อมีการใช้ฟังก์ชัน C เพื่อหยุดชะงักหรือไม่
Emile

ฉันยังไม่ได้เขียนรหัสการรวม Julia-C อย่างไรก็ตามฉันรู้ว่าเป็นเวลานานมากที่มีข้อผิดพลาด segfault เมื่อใดก็ตามที่ระบบใด ๆ ที่ใช้ IO ในหัวข้อ Julia ดังนั้นอาจจะมีปัญหาบางอย่างที่นั่น บางทีในขั้นตอนแรกลองดูว่าเกิดอะไรขึ้นเมื่อคุณเพิ่งพิมพ์ ("boo") โดยไม่ถามขนาดเทอร์มินัล
Przemyslaw Szufel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.