디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

제미니랑 작성한 Ada 코드: posix 시그널 래퍼

나르시갤로그로 이동합니다. 2025.07.23 18:28:10
조회 32 추천 0 댓글 0

네, 우리가 함께 완성한 POSIX 시그널 처리 라이브러리의 전체 소스 코드를 재출력합니다.

이 코드는 다음과 같은 파일들로 구성됩니다.

  1. posix-c.ads: C 기본 타입 및 시그널 상수 정의
  2. posix-unistd.ads / adb: pipe, read, write  unistd 함수 래퍼
  3. posix-signals.ads / adb: sigaction 함수 저수준 래퍼
  4. posix-signal_handler.ads / adb: 최종 고수준 시그널 핸들러 (듀얼 모델 지원)

1. posix-c.ads

-- posix-c.ads

with Interfaces.C;

package POSIX.C is
  pragma Preelaborate;

  type C_int is new Interfaces.C.int;
  type PID_T is new C_int;

  type Signal_Number is new C_int;

  -- Standard Signal Numbers
  SIGHUP    : constant Signal_Number := 1;
  SIGINT    : constant Signal_Number := 2;
  SIGQUIT   : constant Signal_Number := 3;
  SIGILL    : constant Signal_Number := 4;
  SIGTRAP   : constant Signal_Number := 5;
  SIGABRT   : constant Signal_Number := 6;
  SIGKILL   : constant Signal_Number := 9;
  SIGSEGV   : constant Signal_Number := 11;
  SIGPIPE   : constant Signal_Number := 13;
  SIGALRM   : constant Signal_Number := 14;
  SIGTERM   : constant Signal_Number := 15;
  SIGUSR1   : constant Signal_Number := 10;
  SIGUSR2   : constant Signal_Number := 12;
  SIGCHLD   : constant Signal_Number := 17;
  SIGCONT   : constant Signal_Number := 18;
  SIGSTOP   : constant Signal_Number := 19;

  -- Return codes
  SUCCESS : constant C_int := 0;
  FAILURE : constant C_int := -1;

end POSIX.C;

2. posix-unistd.ads

-- posix-unistd.ads

with Ada.Streams;
with Interfaces.C;

package POSIX.Unistd is

  -- Custom exception for POSIX errors
  POSIX_Error : exception;

  -- Type-safe declarations for common identifiers
  type File_Descriptor is new Interfaces.C.int;
  type Process_ID      is new Interfaces.C.int;
  type User_ID         is new Interfaces.C.unsigned;
  type Group_ID        is new Interfaces.C.unsigned;

  -- Standard file descriptors
  STDIN_FD  : constant File_Descriptor := 0;
  STDOUT_FD : constant File_Descriptor := 1;
  STDERR_FD : constant File_Descriptor := 2;

  -- For the pipe() system call
  type Pipe_Ends is record
    Read_End  : File_Descriptor;
    Write_End : File_Descriptor;
  end record;


  -- Process identifier functions
  function get_process_id return Process_ID;
  function get_parent_process_id return Process_ID;
  function fork return Process_ID;

  -- I/O operations
  procedure close_file (fd : in File_Descriptor);
  function read_from
    (fd     : in File_Descriptor;
     buffer : in out Ada.Streams.Stream_Element_Array
  ) return Natural;

  function write_to
    (fd     : in File_Descriptor;
     buffer : in Ada.Streams.Stream_Element_Array
  ) return Natural;

  -- Pipe creation
  procedure create_pipe (ends : out Pipe_Ends);

end POSIX.Unistd;

3. posix-unistd.adb

-- posix-unistd.adb

with Interfaces.C;
with System;

package body POSIX.Unistd is

  -- § Low-level C bindings (private to this package body)
  -------------------------------------------------------
  package C is
    function c_getpid return Process_ID;
    pragma Import (C, c_getpid, "getpid");

    function c_getppid return Process_ID;
    pragma Import (C, c_getppid, "getppid");

    function c_fork return Process_ID;
    pragma Import (C, c_fork, "fork");

    function c_close (fd : File_Descriptor) return Interfaces.C.int;
    pragma Import (C, c_close, "close");

    function c_pipe (fds : System.Address) return Interfaces.C.int;
    pragma Import (C, c_pipe, "pipe");

    function c_read
      (fd  : File_Descriptor;
       buf : System.Address;
       len : Interfaces.C.size_t)
       return Interfaces.C.long; -- ssize_t
    pragma Import (C, c_read, "read");

    function c_write
      (fd  : File_Descriptor;
       buf : System.Address;
       len : Interfaces.C.size_t)
       return Interfaces.C.long; -- ssize_t
    pragma Import (C, c_write, "write");
  end C;

  -- § High-level Ada wrappers
  ---------------------------

  function get_process_id return Process_ID is
  begin
    return C.c_getpid;
  end get_process_id;

  function get_parent_process_id return Process_ID is
  begin
    return C.c_getppid;
  end get_parent_process_id;

  function fork return Process_ID is
    pid : constant Process_ID := C.c_fork;
  begin
    if pid < 0 then
      raise POSIX_Error with "fork failed";
    end if;
    return pid;
  end fork;

  procedure close_file (fd : in File_Descriptor) is
  begin
    if C.c_close (fd) /= 0 then
      raise POSIX_Error with "close failed";
    end if;
  end close_file;

  procedure create_pipe (ends : out Pipe_Ends) is
    fd_array : aliased array (0 .. 1) of Interfaces.C.int;
  begin
    if C.c_pipe (fd_array'Address) /= 0 then
      raise POSIX_Error with "pipe failed";
    end if;
    ends := (Read_End => File_Descriptor (fd_array (0)), Write_End => File_Descriptor (fd_array (1)));
  end create_pipe;

  function read_from
    (fd     : in File_Descriptor;
     buffer : in out Ada.Streams.Stream_Element_Array)
     return Natural
  is
    bytes_read : constant Interfaces.C.long :=
      C.c_read (fd, buffer (buffer'First)'Address, buffer'Length);
  begin
    if bytes_read < 0 then
      raise POSIX_Error with "read failed";
    end if;
    return Natural (bytes_read);
  end read_from;

  function write_to
    (fd     : in File_Descriptor;
     buffer : in Ada.Streams.Stream_Element_Array)
     return Natural
  is
    bytes_written : constant Interfaces.C.long :=
      C.c_write (fd, buffer (buffer'First)'Address, buffer'Length);
  begin
    if bytes_written < 0 then
      raise POSIX_Error with "write failed";
    end if;
    return Natural (bytes_written);
  end write_to;

end POSIX.Unistd;

4. posix-signals.ads

-- posix-signals.ads

with System;
with POSIX.C;

package POSIX.Signals is

  Signal_Error : exception;

  type Signal_Set is private;

  type Signal_Handler is access procedure (Signo : POSIX.C.Signal_Number);
  pragma Convention (C, Signal_Handler);

  -- Default and Ignore handlers
  HANDLER_DEFAULT : constant Signal_Handler := null;
  HANDLER_IGNORE  : constant Signal_Handler := new procedure (Signo : POSIX.C.Signal_Number) is null;

  -- Flags for sa_flags field
  SA_NOCLDSTOP : constant POSIX.C.C_int := 1;
  SA_SIGINFO   : constant POSIX.C.C_int := 4;
  SA_RESTART   : constant POSIX.C.C_int := 16#10000000#;
  SA_RESETHAND : constant POSIX.C.C_int := 16#80000000#;

  type Sigaction_Record is record
    Sa_Handler : Signal_Handler := HANDLER_DEFAULT;
    Sa_Mask    : Signal_Set;
    Sa_Flags   : POSIX.C.C_int := 0;
  end record;

  -- High-level wrapper for sigaction(2)
  procedure set_action (
    signum     : in POSIX.C.Signal_Number;
    action     : in Sigaction_Record;
    old_action : out Sigaction_Record
  );

  -- Signal set management
  procedure empty_set (set : out Signal_Set);

private
  pragma Convention (C, Signal_Set);

  SIGSET_SIZE_BYTES : constant := 128;
  type Signal_Set is array (1 .. SIGSET_SIZE_BYTES) of Interfaces.C.unsigned_char;

end POSIX.Signals;

5. posix-signals.adb

-- posix-signals.adb

with System;
with Interfaces.C;

package body POSIX.Signals is

  -- Low-level C bindings, private to the package body
  ----------------------------------------------------

  type C_Sigaction_Record is record
    Sa_Handler   : Signal_Handler;
    Sa_Mask      : Signal_Set;
    Sa_Flags     : POSIX.C.C_int;
    Sa_Restorer  : System.Address;
  end record;
  pragma Convention (C, C_Sigaction_Record);

  function c_sigaction (
    signum : POSIX.C.Signal_Number;
    act    : access C_Sigaction_Record;
    oldact : access C_Sigaction_Record
  ) return POSIX.C.C_int;
  pragma Import (C, c_sigaction, "sigaction");

  function c_sigemptyset (set : access Signal_Set) return POSIX.C.C_int;
  pragma Import (C, c_sigemptyset, "sigemptyset");

  -- High-level Ada implementations
  ---------------------------------

  procedure set_action (
    signum     : in POSIX.C.Signal_Number;
    action     : in Sigaction_Record;
    old_action : out Sigaction_Record
  ) is
    c_new_action : aliased C_Sigaction_Record;
    c_old_action : aliased C_Sigaction_Record;
    result       : POSIX.C.C_int;
  begin
    c_new_action.Sa_Handler := action.Sa_Handler;
    c_new_action.Sa_Mask    := action.Sa_Mask;
    c_new_action.Sa_Flags   := action.Sa_Flags;
    c_new_action.Sa_Restorer := System.Null_Address;

    result := c_sigaction (signum, c_new_action'Access, c_old_action'Access);

    if result /= POSIX.C.SUCCESS then
      raise Signal_Error with "sigaction failed";
    end if;

    old_action.Sa_Handler := c_old_action.Sa_Handler;
    old_action.Sa_Mask    := c_old_action.Sa_Mask;
    old_action.Sa_Flags   := c_old_action.Sa_Flags;
  end set_action;

  procedure empty_set (set : out Signal_Set) is
  begin
    if c_sigemptyset (set'Access) /= POSIX.C.SUCCESS then
      raise Signal_Error with "sigemptyset failed";
    end if;
  end empty_set;

end POSIX.Signals;

6. posix-signal_handler.ads

-- posix-signal_handler.ads

with POSIX.C;
with POSIX.Unistd;

package POSIX.Signal_Handler is

  Signal_Error : exception;

  type Signal_Set is array (Positive range <>) of POSIX.C.Signal_Number;
  type Signal_Callback is access procedure (signo : in POSIX.C.Signal_Number);

  -- § 모델 A: 내부 태스크와 콜백을 사용하는 간편 모드
  procedure install_callback_handler (
    for_signals : in Signal_Set;
    on_signal   : in Signal_Callback
  );

  -- § 모델 B: 외부 루프를 위해 Pipe FD를 반환하는 수동 모드
  function install_polling_handler (
    for_signals : in Signal_Set
  ) return POSIX.Unistd.File_Descriptor;

  -- § 공통 자원 정리 함수
  procedure terminate_handler;

end POSIX.Signal_Handler;

7. posix-signal_handler.adb

-- posix-signal_handler.adb

with Ada.Streams;
with Ada.Text_IO;
with POSIX.Signals;
with POSIX.Unistd;

package body POSIX.Signal_Handler is

  -- § 패키지 내부 상태 변수
  private_pipe  : POSIX.Unistd.Pipe_Ends;
  is_terminated : Boolean := False;

  -- § Async-signal-safe 핸들러
  procedure pipe_writing_handler (signo : POSIX.C.Signal_Number) is
    signal_byte   : aliased constant Ada.Streams.Stream_Element := Ada.Streams.Stream_Element(signo);
    buffer        : constant Ada.Streams.Stream_Element_Array(1 .. 1) := (1 => signal_byte);
    bytes_written : Natural;
  begin
    if not is_terminated then
      bytes_written := POSIX.Unistd.write_to (private_pipe.Write_End, buffer);
    end if;
  exception
    when others => null;
  end pipe_writing_handler;

  -- § 모델 A를 위한 내부 태스크 및 콜백 변수
  -------------------------------------------
  task type Callback_Dispatcher;
  dispatcher    : Callback_Dispatcher;
  user_callback : Signal_Callback;

  task body Callback_Dispatcher is
    buffer     : aliased Ada.Streams.Stream_Element_Array(1 .. 1);
    bytes_read : Natural;
    signo      : POSIX.C.Signal_Number;
  begin
    loop
      bytes_read := POSIX.Unistd.read_from (private_pipe.Read_End, buffer);
      exit when bytes_read = 0 or else is_terminated;

      signo := POSIX.C.Signal_Number (buffer (1));
      if user_callback /= null then
        begin
          user_callback (signo);
        exception
          when others => null; -- 사용자 콜백의 예외가 태스크를 중단시키지 않도록 함
        end;
      end if;
    end loop;
  exception
    when POSIX.Unistd.POSIX_Error =>
      null; -- 파이프가 닫히면 예외 발생 가능
  end Callback_Dispatcher;


  -- § 공통 핸들러 설치 로직
  --------------------------
  procedure install_common_handler (for_signals : in Signal_Set) is
    action     : POSIX.Signals.Sigaction_Record;
    old_action : POSIX.Signals.Sigaction_Record;
  begin
    is_terminated := False;
    POSIX.Unistd.create_pipe (private_pipe);

    action.Sa_Handler := pipe_writing_handler'Access;
    POSIX.Signals.empty_set (action.Sa_Mask);
    action.Sa_Flags   := POSIX.Signals.SA_RESTART;

    for signo of for_signals loop
      POSIX.Signals.set_action (signo, action, old_action);
    end loop;
  exception
    when others =>
      raise Signal_Error with "Failed to install common signal handler";
  end install_common_handler;


  -- § 공개 인터페이스 구현
  --------------------------
  procedure install_callback_handler (
    for_signals : in Signal_Set;
    on_signal   : in Signal_Callback)
  is
  begin
    user_callback := on_signal;
    install_common_handler (for_signals);
    -- 디스패처 태스크는 자동으로 시작됨
  end install_callback_handler;

  function install_polling_handler (
    for_signals : in Signal_Set
  ) return POSIX.Unistd.File_Descriptor is
  begin
    install_common_handler (for_signals);
    return private_pipe.Read_End;
  end install_polling_handler;

  procedure terminate_handler is
  begin
    if is_terminated then
      return;
    end if;
    is_terminated := True;

    -- 파이프를 닫아 블로킹된 read나 select를 깨운다.
    POSIX.Unistd.close_file (private_pipe.Read_End);
    POSIX.Unistd.close_file (private_pipe.Write_End);

    -- 모델 A의 경우, 태스크가 종료되도록 잠시 기다릴 수 있음
    -- delay 0.1; -- 필요한 경우
  exception
    when POSIX.Unistd.POSIX_Error =>
      null; -- 이미 닫혔을 수 있음
  end terminate_handler;

end POSIX.Signal_Handler;

추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 모태 솔로도 구제해 줄 것 같은 연애 고수 스타는? 운영자 25/07/21 - -
2875011 ❤✨☀⭐⚡☘⛩나님 탈갤합니당⛩☘⚡⭐☀✨❤ [1] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 40 0
2875008 프갤 또 뉴스탈듯.. 운명은 바꿀수 없는걸깡.. [2] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 63 0
2875004 C# 진짜 해보면 만족도가 너무 높긴함 [2] ㅆㅇㅆ(124.216) 07.26 79 0
2875003 성냥사세양..성냥사세양.. 성냥말구 다른것두 팔아양.. [4] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 62 0
2875002 C#에 절여져서 다른 언어를 못하겠다 [4] 루도그담당(58.239) 07.26 75 0
2874999 군대에서 프로그래밍 공부하는법 [3] 프갤러(58.232) 07.26 91 0
2874997 "폭염때문에 너무 뜨거워 마트서 사온 '오리 알'이 부화했어요" 발명도둑잡기(39.7) 07.26 23 0
2874995 커피를 마시며 명상을 하려고 합니다 [15] 아스카영원히사랑해갤로그로 이동합니다. 07.26 88 0
2874993 나님 제 2의 원종이가 나오지 않도록 멍유 케어해주고 있는데.. 뭔가.. [9] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 62 0
2874991 아스카영원히사랑해씨 출입증 나왔습니다 [13] 헬마스터갤로그로 이동합니다. 07.26 68 2
2874989 sap ui5 개좆같다 ㄹㅇ [2] ㅇㅇ(39.7) 07.26 34 0
2874988 저는 크몽, 숨은 고수에서 5만원에 소통과 이야기 할 수 있습니다. [4] ㅆㅇㅆ(124.216) 07.26 66 0
2874986 베르세르크 작가의 생애. ㅇㅇ(183.101) 07.26 28 0
2874984 ㅆㅇㅆ과 진지한 대화를 하고 싶다 [3] 아스카영원히사랑해갤로그로 이동합니다. 07.26 66 0
2874983 뉴프로 전환율을 높이기 위해 비회원 댓글창을 표시하다 헬마스터갤로그로 이동합니다. 07.26 27 0
2874982 요즘 인싸들 진격거보고 꺼드럭거리는거 개빡침 [4] 어린이노무현갤로그로 이동합니다. 07.26 70 2
2874981 원종이 IQ 높았냐? [4] ㅇㅇ(211.234) 07.26 57 0
2874980 누가 나님 냥덩이 만진거야? [5] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 56 0
2874978 흔한 화상회의 ㅇㅇ(183.101) 07.26 28 0
2874977 자기가 조건을 거는 순간 보지가 조건을 걸어도 인정을 해야지; [4] ㅆㅇㅆ(124.216) 07.26 66 0
2874974 유니티 발 문제 해결했다 [4] 루도그담당(58.239) 07.26 59 0
2874971 나님 인간 공부즁.. [1] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 41 0
2874966 칸예가 지지했던 트럼프가 당선돼야 발명도둑잡기(39.7) 07.26 25 0
2874964 난 남자지만 여자들이 차 없는 남자 안만나는거 이해함 [4] ㅇㅇ(211.234) 07.26 67 2
2874963 멱등성이라는 개념이랑 불변성 헷갈렸는데 [6] ㅆㅇㅆ(124.216) 07.26 49 0
2874962 인류말살계획 ㅇㅅㅇ [1] 어린이노무현갤로그로 이동합니다. 07.26 43 0
2874961 오늘도 코드 공부를 끝냈다. Saga패턴을 오늘도 완벽히 구현한 나 [3] ㅆㅇㅆ(124.216) 07.26 40 0
2874960 <어쩔 수가 없다> 발명도둑잡기(39.7) 07.26 25 0
2874959 플러터 인형 갖고싶댱❤ [7] 어린이노무현갤로그로 이동합니다. 07.26 53 0
2874958 호감고닉 등장 [4] 호감고닉(121.168) 07.26 42 0
2874957 러스트 정신병자 특) 나르시갤로그로 이동합니다. 07.26 31 0
2874955 신주라는 문화에 대해서 알고있다면 [2] 개멍청한유라갤로그로 이동합니다. 07.26 50 0
2874952 Ada의 심각한 단점: 타입 이름을 네임스페이스로 사용할 수 없다 [1] 나르시갤로그로 이동합니다. 07.26 45 0
2874950 이 더위에 도로롱 행사 보러 간 프갤러 발명도둑잡기(39.7) 07.26 22 0
2874948 토스는 왜이렇게 학벌이 안좋냐 [3] 프갤러(124.53) 07.26 80 0
2874946 디시에서 도움좀 받아서 오픈카톡으로 송금좀 해줬는데 [1] ㅇㅇ(110.10) 07.26 29 0
2874945 부산 30도 대구 33 사울37 프갤러(183.101) 07.26 39 0
2874944 장문주의) 나님 애널 도로롱 행사 후기 [5] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 44 0
2874942 안드로이드 온도계 발명도둑잡기(39.7) 07.26 20 0
2874938 요즘 날벌레 별루 없눈둣? ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 20 0
2874930 술렁..술렁.. 야옹.. 냐옹.. [5] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 54 0
2874929 충전기랑 어댑터 C to C 로 통일해도 문제 없을까요? 질문왕(211.248) 07.26 19 0
2874923 동태 눈깔에 는 동태만 보인다고 합니다. 국민의힘 색깔론 넥도리나(220.74) 07.26 24 0
2874919 안경 셀프로 고쳤습니다. 자가수리 나사가 있어서 넥도리나(220.74) 07.26 17 0
2874917 냥덩이의 여름 훈련법⭐+ [2] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 33 0
2874913 나님 누엇어양⭐+ [1] ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.26 27 0
2874912 존 나 더 워 [7] 아스카영원히사랑해갤로그로 이동합니다. 07.26 54 0
2874911 서울날씨 개쓰레기 [3] 프갤러(183.101) 07.26 48 0
2874910 내가 보는 Ada 언어 최대 문제점 ㅋㅋ 나르시갤로그로 이동합니다. 07.26 32 0
2874908 안경이 부러졌다 불광동 또가야 하나... ㅠㅠㅠ 넥도리나(220.74) 07.26 17 0
뉴스 ‘밤톨 머리’ 차은우 “실감 안 나…잊지 말아줘” 디시트렌드 07.26
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2