디시인사이드 갤러리

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

갤러리 본문 영역

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

나르시갤로그로 이동합니다. 2025.07.23 18:28:10
조회 49 추천 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/09/01 - -
AD 가전디지털, 신학기 페스타! 운영자 25/08/29 - -
2885204 뉴프로 시크릿 산타 기능 추가 안내 헬마스터갤로그로 이동합니다. 08.28 53 0
2885202 술 끊는게 인지능력, 생활습관, 체력 개선에 지대한 영향을 끼치냐?? [1] ㅇㅇ(223.38) 08.28 68 0
2885197 [1인 1개] 배달의 민족 3 만원 짜리 쓸사람 써! [1] ㅇㅇ(223.39) 08.28 55 0
2885195 오피 갔다온 썰 함 풀어봄ㅋ ㅋㅋ ㅇㅇ(118.235) 08.28 98 0
2885194 ai로 다 대체 되니까 프갤 망했냐? [1] 프갤러(59.11) 08.28 100 0
2885193 파이썬 초초보 질문 [1] 프갤러(59.11) 08.28 58 0
2885191 윈도우임베 미래없다는말이 젤 개소리인게 [3] 네오커헠(211.234) 08.28 126 0
2885190 자꾸 기술스택 처바꿔대서 짜증난다. 프갤러(211.234) 08.28 65 0
2885183 세상엔 좆병신이 많은 것 같다 [3] 아스카영원히사랑해갤로그로 이동합니다. 08.28 93 0
2885181 또 하나 더... 넥도리아(220.74) 08.28 53 0
2885180 통수조심해라 [1] 프갤러(211.170) 08.28 81 2
2885178 부침개 먹는다. [1] 넥도리아(220.74) 08.28 70 0
2885177 아 존나 배고파 루도그담당(118.235) 08.28 49 0
2885176 저는 가짜 개발자입니다 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ [2] 공기역학갤로그로 이동합니다. 08.28 108 3
2885174 요즘은 마크개발자놀이역할 로블록스가 한다고 들은거같음 공기역학갤로그로 이동합니다. 08.28 54 0
2885173 님들, 딥시크 모델 무료/무제한으로 풀림 ㄷㄷ (정보 공유) 무한루프갤로그로 이동합니다. 08.28 57 0
2885170 님들 컴공 졸업할때 cpa 응시자격같은거 채웠음? [3] 공기역학갤로그로 이동합니다. 08.28 100 0
2885169 하루에 오보오경억만무량대수줄 감사의 코딩 공기역학갤로그로 이동합니다. 08.28 41 0
2885168 저도 웹개발 하다가 적성에 안맞아요 프갤러(118.235) 08.28 68 0
2885166 sql 연습 이런 사이트 없나 [1] 프갤러(118.235) 08.28 60 0
2885165 솽.. 나가야 대는대..ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08.28 38 0
2885164 ISTP 개발자분 계신지? [1] 프갤러(106.242) 08.28 79 0
2885163 코딩 적성에 맞는지 (간단하게) 확인하는법(고딩용) [3] 프갤러(125.135) 08.28 117 0
2885162 1인개발자인데 개발자 구하려는데 페이 얼마나 주면됨? [3] 프갤러(112.187) 08.28 89 0
2885161 1인개발자 구인은 어디서함? 프갤러(112.187) 08.28 50 0
2885160 취업 힘들까요?? 딱좋노갤로그로 이동합니다. 08.28 66 0
2885159 자식이 주는 행복도 있구나 루도그담당(118.235) 08.28 58 0
2885154 누구는 차은우 누구는 김성수여도 기득권들은 대부분 좇같은새끼들이라는거 ㅎ 뒷통수한방(1.213) 08.28 55 0
2885152 좇센에서 태어나는게 간접체험이 누구는 김성수 인생 누구는 차은우 인생 [1] 뒷통수한방(1.213) 08.28 64 0
2885151 깃 잘 모르는 사람이 나보다 직급 높으니까 기분 더럽네 프갤러(218.154) 08.28 62 0
2885150 프로그래밍 하면 맘에 드는 코드 까서 저장해놓잖아 [7] ㅆㅇㅆ(124.216) 08.28 141 0
2885148 리버싱 니네도 해보셈 [2] 루도그담당(118.235) 08.28 84 0
2885147 그냥 이론 실무서적보고 남의 게임이랑 코드까보면 되잖아 [7] ㅆㅇㅆ찡갤로그로 이동합니다. 08.28 103 0
2885146 [애니뉴스] 귀인환등초 잡지 2호 포스터 공개- 프갤러(121.172) 08.28 47 0
2885145 하는일이 점점 산으로 가는데.. 어케해야하나... [9] 프갤러(175.125) 08.28 97 0
2885144 애초에 항상 최신 스택 이런건 그냥 학원들 약팔이일뿐임. ㅆㅇㅆ(124.216) 08.28 56 0
2885143 데비안13 조져버림 이기이기 [3] 뒷통수한방(1.213) 08.28 80 0
2885142 근데 도태랄게 있나 애초에 시장이랑 기술적 최신 스택이랑 일치 안함 [2] ㅆㅇㅆ(124.216) 08.28 97 0
2885141 자료구조 책?강의?추천좀 해주세요 [5] 프갤러(118.32) 08.28 86 0
2885139 매번 항상 느끼지만 이론의 아름다운과 실제 현장은 괴리가 있음 ㅆㅇㅆ(124.216) 08.28 51 0
2885138 회사의 유일한 프로그래머로 꿀 빨고 있는데 인생 망해가는듯 [8] 프갤러(220.124) 08.28 125 0
2885137 개발자 커뮤? [3] 중생들아갤로그로 이동합니다. 08.28 89 0
2885136 [애니뉴스](스포일러) 귀인환등초 2호잡지 - 노마리 관련되어 - 프갤러(121.172) 08.28 34 0
2885134 우울하다 [4] 주아갤로그로 이동합니다. 08.28 65 0
2885131 유퀴즈보바라 빌게이츠의 위대함을 느껴라 ㅇㅇ 타이밍뒷.통수한방(1.213) 08.28 74 0
2885130 아키텍트 읽을때마다 느끼지만 내가 느끼는게 아키텍트 없는게 더 많더라. ㅆㅇㅆ(124.216) 08.28 61 0
2885129 30대 무경력 고졸 2트국비충 [1] 프갤러(106.101) 08.28 126 0
2885125 cto가 프로세스랑 스레드 개념을 아예 모르는데 [5] ㅇㅇ(211.234) 08.28 97 0
2885124 웹 만들면서 느끼는데 게임은 돈 진짜 말도 안되게 드는거였구나 [2] ㅆㅇㅆ(124.216) 08.28 107 0
2885123 울 어머니가 타로 앱 만들었으면 하는것도 있고 [2] ㅆㅇㅆ(124.216) 08.28 72 0
뉴스 Honor Flow Productions∙KORB∙오아, 8월 4주 차 위클리 키트앨범 스포트라이트 선정! 일상을 채우는 음악! 디시트렌드 08.29
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2