Hệ thống chặn tín hiệu ở Julia


9

Trong một chương trình Julia chạy trên Linux, tôi cần khởi chạy một hành động chuyên dụng khi cửa sổ giao diện điều khiển được thay đổi kích thước. Vậy làm thế nào trong Julia, tôi có thể chặn tín hiệu hệ thống SIGWINCH (thay đổi kích thước cửa sổ) và gắn vào nó một chức năng thực hiện hành động cần thiết?

Trong Ada, việc khai báo nó khá đơn giản:

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

GIẢI PHÁP NHIỆM VỤ DỰA TRÊN IDEA CỦA SCHEMER: Tôi cố gắng sử dụng Thư viện C để thực hiện giám sát gián đoạn SIGWINCH.

thư viện của tôi

void Winresize (void Sig_Handler());

thư viện của tôi

#include "myLibrary.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void Winresize(void sig_handler (void)) { 
     signal(SIGWINCH, sig_handler);
}

Biên soạn & chuẩn bị thư viện

gcc -c -Wall -fPIC myL Library.c

gcc-Shared -fPIC -o myL Library.so myL Library.o

Chương trình tại Julia sử dụng Thư viện C:

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 

Chương trình Julia chạy đúng nhưng khi cửa sổ đầu cuối được thay đổi kích thước, một lỗi Phân đoạn (lõi bị đổ) được phát hành và chương trình được cho là đã thoát với mã: 139.

Vì vậy, câu hỏi là lỗi phân khúc này đến từ đâu? Từ mô hình biên soạn? Julia không có quyền kiểm soát việc thực thi mã trong phần bộ nhớ trong đó C quản lý giám sát tín hiệu?

Loại bỏ hoạt động println trong Sig_handler ngăn chặn lỗi phân đoạn:

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
Nó khá đơn giản để hiện thực hóa điều này như một mô-đun SignalHandlers.jl bằng cách sử dụng ccall ((: signal ...) và @cfactor, nhưng AFAIK điều này đã không được thực hiện.
Bill

Đề nghị của bạn là một trong những tốt. Cảm ơn bạn.
Emile

Câu trả lời:


4

Vì không ai trả lời câu hỏi này cho đến nay, một cách giải quyết có thể có thể là giám sát không đồng bộ kích thước của thiết bị đầu cuối trong một số khoảng thời gian.

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

Và bây giờ sử dụng mẫu:

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

Miễn là thiết bị đầu cuối còn sống, mọi thay đổi về kích thước của nó sẽ được in BOO!.


Tôi không biết cách tốt đẹp này để có được kích thước cửa sổ giao diện điều khiển hiện tại. displayize (stdout) Cảm ơn bạn
Emile

0

Vâng, đó thực sự là một giải pháp dự phòng mà hầu như không ai mong đợi từ một ngôn ngữ mới đầy hứa hẹn ... nhưng vì thiếu sự tưa lưỡi, chúng ta thực sự có thể ăn chim đen (cười).

Nhưng nếu Julia không có kế hoạch có thể tính đến các tín hiệu hệ thống của thế giới Unix / Linux, thì có thể sử dụng thư viện C giống như thư viện mà tín hiệu truy cập.

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

Chúng ta sẽ phải xác định một hàm julia làm những gì được mong đợi khi nhận được tín hiệu hệ thống. Làm cho nó có thể sử dụng được trong C là Sig_handler và gọi từ julia tín hiệu câu lệnh C (SIGWINCH, Sig_handler);

Tôi không đủ quen thuộc với julia để viết mã chính xác. Nhưng đây là ý tưởng ...


Tôi sẽ cố gắng thực hiện những gì bạn đề xuất.
Emile

@Emile nếu bạn quản lý để thực hiện nó (bao gồm cả viết Jullia ccal) và sau này muốn biến nó thành gói Julia tiêu chuẩn tôi có thể giúp đóng gói.
Przemyslaw Szufel

Ghi nhận hợp lệ ! Tôi phải đi xa hơn một chút trong tài liệu julia.
Emile

@Przemyslaw Szufel: Phân tích của bạn về lỗi phân đoạn được hiển thị ở trên là bổ sung cho câu hỏi của tôi và xảy ra khi chức năng C được sử dụng để bắt gián đoạn?
Emile

Tôi chưa viết mã tích hợp Julia-C. Tuy nhiên, tôi biết rằng trong một thời gian rất dài đã xảy ra lỗi segfault mỗi khi bất kỳ hệ thống IO nào được sử dụng trong các luồng của Julia nên có thể có một số vấn đề ở đó. Có thể trong bước đầu tiên hãy thử xem điều gì xảy ra khi bạn chỉ in println ("boo") mà không yêu cầu kích thước thiết bị đầu cuối.
Przemyslaw Szufel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.