디시인사이드 갤러리

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

갤러리 본문 영역

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

나르시갤로그로 이동합니다. 2025.07.23 18:28:10
조회 38 추천 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/28 - -
AD 휴대폰 액세서리 세일 중임! 운영자 25/07/28 - -
2874115 나님의 우울증 치료제는 에반게리온이었다 [3] 아스카영원히사랑해갤로그로 이동합니다. 07.24 81 0
2874114 애반게리온 보고 치유된과정 - eoe 랑 tva 후기 [4] 프갤러(183.101) 07.24 65 0
2874113 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 32 0
2874112 나님 사교용 춤 배울깡 생각즁⭐+ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 35 0
2874111 곧 3년차인데 이제 이직 자리 알아봐야지 [1] 프갤러(118.235) 07.24 66 0
2874110 결국 프로그래밍이란 무엇인가 ㅆㅇㅆ찡갤로그로 이동합니다. 07.24 68 0
2874109 데이터 복구 맡기러 왔다가 집에와서 콩국수 먹었는데 인생에 덧이 없구나. 넥도리아(220.74) 07.24 41 0
2874108 프로그래밍의 개인적 허들은 실재적구조에서 개념적 구조로 ㅆㅇㅆ찡갤로그로 이동합니다. 07.24 57 0
2874107 2찢명 매번 미국에 입구컷 쫓겨나는꼴 ㄹㅇ 현웃터짐 ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 41 0
2874106 2찢명 사람 쓰고 버리기 스킬 ㅆㅅㅌㅊ! ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 34 0
2874105 짱깨들도 2찢명 쿠폰으로 한국세금 달달하거이 빨아먹는즁 ㅋㅅㅋ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 35 0
2874104 물리 배우다 프로그래밍으로 넘어가서 편했던점 [2] ㅆㅇㅆ찡갤로그로 이동합니다. 07.24 73 0
2874103 나님만큼 최신 기술에 거부감 없이 잘쓰는 인재는 드뭄 ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 42 0
2874102 여기서 조언바래봤자 딴데 가는게 나음 [2] ㅆㅇㅆ찡갤로그로 이동합니다. 07.24 58 0
2874101 나님이 이번에 실험중인 항목들 ㅇㅅㅇ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 33 0
2874100 2ㅌㅊ 까지는 올해마무리 할지 모르겠넹 ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 39 0
2874099 늒비 간곡한 조언 부탁드립니다 [1] 프갤러(203.10) 07.24 49 0
2874098 요즘 사람들 이를 안 닦나보군요 루도그담당(211.184) 07.24 51 0
2874097 중간 일정까지 고려하면 올해 간당하겠고 ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 30 0
2874096 단순 계산으로 75면.. 흠.. ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 30 0
2874095 내일 출근 안합니다 ㅋ 루도그담당(211.184) 07.24 44 0
2874093 지방은 경력 10년도 연봉 5천 미만 수두룩하네 프갤러(218.238) 07.24 51 0
2874092 웹 영상 drm 걸린건 왠만해선 복호화 불가능함? [8] ㅇㅇ(110.10) 07.24 97 0
2874091 프로그래밍 솔직히 한 5~6년전 코드보면 기억 안나서 느끼는거지만 [1] ㅆㅇㅆ(124.216) 07.24 62 0
2874090 나님 통찰력 ㄱㅆㅅㅌㅊ.. ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 36 0
2874089 언젠간 이 문서를 완성하는게 내 개인적 목표임 [2] ㅆㅇㅆ(124.216) 07.24 58 0
2874088 저기 밑에 WPF 예제 추천해줌 ㅇㅇ [4] ㅆㅇㅆ(124.216) 07.24 75 0
2874087 C#에서 고급 문법이랄게 뭐가 있을까 [1] 루도그담당(211.184) 07.24 60 0
2874086 C# WPF에 윈폼이면 그렇게 어려울거 없이 1년투자하면 될거같은데 [5] ㅆㅇㅆ(124.216) 07.24 96 0
2874085 내가 느끼는건 프로그래밍하다보면 자신만의 기술 개념의 계층이 필요함 [2] ㅆㅇㅆ(124.216) 07.24 68 0
2874083 나는 항상 프로그래밍 메타 따라갈려고 체크중인데 내가 느끼는게 ㅆㅇㅆ(124.216) 07.24 52 0
2874082 마음아프고 애정결핍애들 애반게리온 필수시청 [4] 프갤러(183.101) 07.24 49 0
2874081 날씨 미쳤네 진짜 루도그담당(211.184) 07.24 42 0
2874080 공수처 검찰청 경찰청 국제수사 과학수사 포랜식수사 기무사 국정원 존재이유 뒷통수한방(1.213) 07.24 30 0
2874079 봇찌 css로 만들어봄 [5] ㅇㅇ(125.205) 07.24 69 1
2874078 근데 권도형 미국 갔잖아 그래서 뭐 언급없는거 아닌가? [3] ㅆㅇㅆ(124.216) 07.24 58 0
2874076 님들 루나코인 폭락 사건 알음? [1] 프갤러(222.114) 07.24 60 0
2874075 오 대기업들 슬슬 시작하려는듯 ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 51 0
2874074 인정에서 발전이 시작되는법 ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 39 0
2874073 나님 회복탄력성 실험즁❤+ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 41 0
2874072 나님 25억 인증❤+ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 48 0
2874071 개인적으로 느끼는거지만 결국 프로그래밍은 어떤 글쓰기 스타일이냐가 [2] ㅆㅇㅆ(124.216) 07.24 84 2
2874070 길가다 찍은 일본의 묘한 선거포스터 [9] 아스카영원히사랑해갤로그로 이동합니다. 07.24 107 0
2874069 최악무능 친중좌파 2찢명 입구컷! ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 47 0
2874068 신입, 주니어 취준생들 이력서 첨삭해줌 프갤러(221.148) 07.24 45 0
2874067 우낏낏끼! 우키킼! [1] 통암기원숭이(211.235) 07.24 57 0
2874066 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥팬티스타킹냥덩♥갤로그로 이동합니다. 07.24 34 0
2874065 파이어 베이스 쓰는게 나을까? 프갤러(39.118) 07.24 37 0
2874064 MSA가 꼭 크기는 클 필요 없긴함 ㅆㅇㅆ(124.216) 07.24 43 0
2874063 30대 모솔아다 지잡 비전공 백수 무직 [2] 어린이노무현갤로그로 이동합니다. 07.24 89 0
뉴스 김혜수, 윤상현과 다정한 모습…‘영화관 데이트’ 포착 디시트렌드 10:00
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2