home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / m2posx14 / test / tsighand.mpp < prev    next >
Encoding:
Text File  |  1994-05-29  |  12.4 KB  |  440 lines

  1. MODULE tsighandler;
  2. __IMP_SWITCHES__
  3. __DEBUG__
  4. #ifdef HM2
  5. #ifdef __LONG_WHOLE__
  6. (*$!i+: Modul muss mit $i- uebersetzt werden! *)
  7. (*$!w+: Modul muss mit $w- uebersetzt werden! *)
  8. #else
  9. (*$!i-: Modul muss mit $i+ uebersetzt werden! *)
  10. (*$!w-: Modul muss mit $w+ uebersetzt werden! *)
  11. #endif
  12. #endif
  13. VAL_INTRINSIC
  14.  
  15. (* Test und Anwendungsbeispiel fuer Signalfunktionen, die direkt mit
  16.  * Signalhandlern zu tun haben. Laeuft unter TOS und MiNT.
  17.  *
  18.  * 29-Mai-94, Holger Kleinschmidt
  19.  *)
  20.  
  21. #if (defined MM2) && (defined __DEBUG_CODE__)
  22. IMPORT Debug;
  23. #endif
  24.  
  25. FROM SYSTEM IMPORT
  26. (* PROC *) ADR;
  27.  
  28. FROM PORTAB IMPORT
  29. (* CONST*) NULL,
  30. (* TYPE *) UNSIGNEDLONG;
  31.  
  32. FROM types IMPORT
  33. (* TYPE *) int;
  34.  
  35. IMPORT e;
  36.  
  37. FROM OSCALLS IMPORT
  38. (* PROC *) Cconws;
  39.  
  40. FROM cstr IMPORT
  41. (* PROC *) strerror, AssignCToM2;
  42.  
  43. FROM jump IMPORT
  44. (* CONST*) SAVE, NOSAVE,
  45. (* TYPE *) SigJmpBuf,
  46. (* PROC *) sigsetjmp, siglongjmp;
  47.  
  48. FROM sig IMPORT
  49. (* CONST*) SigDfl, SigIgn, SIGUSR1, SIGUSR2,
  50. (* TYPE *) sigsetT, SignalHandler, SigactionRec, SigBlockType, SaFlags,
  51.            SigsetPtr,
  52. (* PROC *) signal, raise, sigemptyset, sigaddset, sigismember, sigaction,
  53.            sigprocmask, sigpending, sigmask, sigblock, sigsetmask;
  54.  
  55. FROM Terminal IMPORT
  56. (* PROC *) WriteString, WriteLn, Read;
  57.  
  58. (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
  59.  
  60. CONST JUMPVAL = 42;
  61.  
  62. TYPE
  63.   SetCast = RECORD
  64.     CASE TAG_COLON BOOLEAN OF
  65.       FALSE: sigset  : sigsetT;
  66.      |TRUE : siglong : UNSIGNEDLONG;
  67.     END;
  68.   END;
  69.  
  70. VAR newh, oldh : SignalHandler;
  71.     new, old   : SigactionRec;
  72.     oldm, newm : SetCast;
  73.     save       : UNSIGNEDLONG;
  74.     c          : CHAR;
  75.     handled    : BOOLEAN;
  76.     buf        : SigJmpBuf;
  77.     jmpval     : INTEGER;
  78.     void       : INTEGER;
  79.     errmsg     : ARRAY [0..50] OF CHAR;
  80.  
  81. (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
  82.  
  83. PROCEDURE tsignal ((* EIN/ -- *) REF par      : ARRAY OF CHAR;
  84.                    (* EIN/ -- *)     sig      : int;
  85.                    (* EIN/ -- *)     newh     : SignalHandler;
  86.                    (* EIN/ -- *)     expected : SignalHandler );
  87.  
  88. VAR oldh : SignalHandler;
  89.  
  90. BEGIN
  91.  WriteString("tsignal["); WriteString(par); WriteString("]: ");
  92.  IF signal(sig, newh, oldh) < 0 THEN
  93.    AssignCToM2(strerror(e.errno), 0, errmsg);
  94.    WriteString("***: "); WriteString(errmsg);
  95.  ELSIF oldh.long <> expected.long THEN
  96.    WriteString("***: unexpected old handler");
  97.  ELSE
  98.    WriteString("OK");
  99.  END;
  100.  WriteLn;
  101. END tsignal;
  102.  
  103. (*---------------------------------------------------------------------------*)
  104.  
  105. PROCEDURE tsigaction ((* EIN/ -- *) REF par      : ARRAY OF CHAR;
  106.                       (* EIN/ -- *)     sig      : int;
  107.                       (* EIN/ -- *)     new      : SigactionRec;
  108.                       (* EIN/ -- *)     expected : SigactionRec );
  109.  
  110. VAR old  : SigactionRec;
  111.     set1 : SetCast;
  112.     set2 : SetCast;
  113.  
  114. BEGIN
  115.  WriteString("tsigaction["); WriteString(par); WriteString("]: ");
  116.  IF sigaction(sig, ADR(new), ADR(old)) < 0 THEN
  117.    AssignCToM2(strerror(e.errno), 0, errmsg);
  118.    WriteString("***: "); WriteString(errmsg);
  119.  ELSIF old.saHandler.long <> expected.saHandler.long THEN
  120.    WriteString("***: unexpected old handler");
  121.  ELSIF old.saFlags <> expected.saFlags THEN
  122.    WriteString("***: unexpected old flags");
  123.  ELSE
  124.    set1.sigset := old.saMask;
  125.    set2.sigset := expected.saMask;
  126.    IF set1.siglong <> set2.siglong THEN
  127.      WriteString("***: unexpected old mask");
  128.    ELSE
  129.      WriteString("OK");
  130.    END;
  131.  END;
  132.  WriteLn;
  133. END tsigaction;
  134.  
  135. (*---------------------------------------------------------------------------*)
  136.  
  137. PROCEDURE tsigprocmask ((* EIN/ -- *) how : SigBlockType;
  138.                         (* EIN/ -- *) new : SigsetPtr;
  139.                         (* EIN/ -- *) old : SigsetPtr );
  140.  
  141. BEGIN
  142.  IF sigprocmask(how, new, old) < 0 THEN
  143.    errmsg := "*** tsigprocmask: ";
  144.    Cconws(ADR(errmsg));
  145.    AssignCToM2(strerror(e.errno), 0, errmsg);
  146.    Cconws(ADR(errmsg));
  147.  END;
  148. END tsigprocmask;
  149.  
  150. (*---------------------------------------------------------------------------*)
  151.  
  152. PROCEDURE tsigpending ((* EIN/ -- *) REF par      : ARRAY OF CHAR;
  153.                        (* EIN/ -- *)     expected : SetCast       );
  154.  
  155. VAR old : SetCast;
  156.  
  157. BEGIN
  158.  WriteString("tsigpending["); WriteString(par); WriteString("]: ");
  159.  IF sigpending(old.sigset) < 0 THEN
  160.    AssignCToM2(strerror(e.errno), 0, errmsg);
  161.    WriteString("***: "); WriteString(errmsg);
  162.  ELSIF old.siglong <> expected.siglong THEN
  163.    WriteString("***: unexpected pending signals");
  164.  ELSE
  165.    WriteString("OK");
  166.  END;
  167.  WriteLn;
  168. END tsigpending;
  169.  
  170. (*---------------------------------------------------------------------------*)
  171.  
  172. PROCEDURE traise ((* EIN/ -- *) REF par : ARRAY OF CHAR;
  173.                   (* EIN/ -- *)     now : BOOLEAN;
  174.                   (* EIN/ -- *)     sig : int           );
  175. BEGIN
  176.  WriteString("traise["); WriteString(par); WriteString("]: ");
  177.  handled := FALSE;
  178.  IF raise(sig) < 0 THEN
  179.    AssignCToM2(strerror(e.errno), 0, errmsg);
  180.    WriteString("***: "); WriteString(errmsg);
  181.    WriteLn;
  182.  ELSIF now AND NOT handled THEN
  183.    WriteString("***: signal not handled");
  184.  ELSIF NOT now AND handled THEN
  185.    WriteString("***: signal handled");
  186.  ELSE
  187.    WriteString("OK");
  188.  END;
  189.  WriteLn;
  190. END traise;
  191.  
  192. (*---------------------------------------------------------------------------*)
  193.  
  194. PROCEDURE traisejump ((* EIN/ -- *) REF par  : ARRAY OF CHAR;
  195.                       (* EIN/ -- *)     sig  : int;
  196.                       (* EIN/ -- *)     save : BOOLEAN       );
  197.  
  198. VAR jumpval : INTEGER;
  199.  
  200. BEGIN
  201.  WriteString("traisejump["); WriteString(par); WriteString("]: ");
  202.  handled := FALSE;
  203.  jmpval  := sigsetjmp(buf, ORD(save));
  204.  IF jmpval = 0 THEN
  205.    (* Wenn alles stimmt, kehrt der Aufruf nicht zurueck! *)
  206.    IF raise(sig) < 0 THEN
  207.      AssignCToM2(strerror(e.errno), 0, errmsg);
  208.      WriteString("***: "); WriteString(errmsg);
  209.    ELSE
  210.      WriteString("***: jump failed");
  211.    END;
  212.    WriteLn;
  213.  ELSIF jmpval <> JUMPVAL THEN
  214.    WriteString("***: unexpected jump-val");
  215.  ELSIF NOT handled THEN
  216.    WriteString("***: signal not handled");
  217.  ELSE
  218.    WriteString("OK");
  219.  END;
  220.  WriteLn;
  221. END traisejump;
  222.  
  223. (*---------------------------------------------------------------------------*)
  224.  
  225. #ifdef HM2
  226. (*$E+,$K+*)
  227. #endif
  228. PROCEDURE handler1 (sig : UNSIGNEDLONG);
  229. (* ``normaler'' Signalhandler *)
  230. BEGIN
  231.  handled := TRUE;
  232. END handler1;
  233.  
  234. (*---------------------------------------------------------------------------*)
  235.  
  236. PROCEDURE handler2 (sig : UNSIGNEDLONG);
  237. (* Signalhandler, der nicht zurueckkehrt *)
  238. VAR mask : SetCast;
  239.     cmp  : SetCast;
  240.     save : INTEGER;
  241.     void : INTEGER;
  242.  
  243. BEGIN
  244.  handled := TRUE;
  245.  save := e.errno; (* Hier eigtl. nicht noetig *)
  246.  sigemptyset(cmp.sigset);
  247.  void := sigaddset(cmp.sigset, INT(sig));
  248.  tsigprocmask(SigSetMask, NULL, ADR(mask.sigset));
  249.  IF mask.siglong <> cmp.siglong THEN
  250.    errmsg := "<< *** handler2: unexpected signal mask >> ";
  251.  ELSE
  252.    errmsg := "<< handler2: signal mask OK >> ";
  253.  END;
  254.  Cconws(ADR(errmsg));
  255.  e.errno := save;
  256.  siglongjmp(buf, JUMPVAL);
  257. END handler2;
  258.  
  259. (*---------------------------------------------------------------------------*)
  260.  
  261. PROCEDURE handler3 (sig : UNSIGNEDLONG);
  262. (* Signalhandler, der nicht zurueckkehrt *)
  263. VAR mask : SetCast;
  264.     cmp  : SetCast;
  265.     save : INTEGER;
  266.     void : INTEGER;
  267.  
  268. BEGIN
  269.  handled := TRUE;
  270.  save := e.errno; (* Hier eigtl. nicht noetig *)
  271.  sigemptyset(cmp.sigset);
  272.  void := sigaddset(cmp.sigset, INT(sig));
  273.  void := sigaddset(cmp.sigset, SIGUSR2);
  274.  tsigprocmask(SigSetMask, NULL, ADR(mask.sigset));
  275.  IF mask.siglong <> cmp.siglong THEN
  276.    errmsg := "<< *** handler3: unexpected signal mask >> ";
  277.  ELSE
  278.    errmsg := "<< handler3: signal mask OK >> ";
  279.  END;
  280.  Cconws(ADR(errmsg));
  281.  e.errno := save;
  282.  siglongjmp(buf, JUMPVAL);
  283. END handler3;
  284. #ifdef HM2
  285. (*$E=,$K-*)
  286. #endif
  287.  
  288. (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
  289.  
  290. BEGIN
  291.  (* 'handler1' als Signalhandler fuer SIGUSR1 installieren. Der alte Handler
  292.   * muss die Defaultaktion sein.
  293.   *)
  294.  newh.proc := handler1;
  295.  oldh.long := SigDfl;
  296.  tsignal("sig=SIGUSR1 new=handler1 old=SIG_DFL", SIGUSR1, newh, oldh);
  297.  
  298.  (* Am Anfang steht kein Signal an *)
  299.  sigemptyset(newm.sigset);
  300.  tsigpending("pending={}", newm);
  301.  
  302.  (* SIGUSR1 blockieren *)
  303.  void := sigaddset(newm.sigset, SIGUSR1);
  304.  tsigprocmask(SigBlock, ADR(newm.sigset), NULL);
  305.  
  306.  (* SIGUSR1 ausloesen, Signal darf aber nicht gesendet werden, nur vermerkt *)
  307.  traise("sig=SIGUSR1", FALSE, SIGUSR1);
  308.  
  309.  (* SIGUSR1 muss jetzt anstehen *)
  310.  tsigpending("pending={SIGUSR1}", newm);
  311.  
  312.  (* Blockierung fuer SIGUSR1 aufheben, Signal muss jetzt gesendet werden *)
  313.  handled := FALSE;
  314.  tsigprocmask(SigUnBlock, ADR(newm.sigset), NULL);
  315.  IF NOT handled THEN
  316.    WriteString("*** Signal not handled");
  317.  ELSE
  318.    WriteString("Signal handled OK");
  319.  END;
  320.  WriteLn;
  321.  
  322.  (* jetzt darf kein Signal mehr anstehen *)
  323.  sigemptyset(oldm.sigset);
  324.  tsigpending("pending={}", oldm);
  325.  
  326.  tsigprocmask(SigSetMask, NULL, ADR(newm.sigset));
  327.  sigemptyset(oldm.sigset);
  328.  IF oldm.siglong = newm.siglong THEN
  329.    WriteString("sigprocmask: signal mask OK");
  330.  ELSE
  331.    WriteString("*** sigprocmask: unexpected signal mask");
  332.  END;
  333.  WriteLn;
  334.  
  335.  
  336.  (* SIGUSR1 blockieren *)
  337.  save := sigblock(sigmask(SIGUSR1));
  338.  
  339.  (* SIGUSR1 ausloesen, Signal darf aber nicht gesendet werden, nur
  340.   * vermerkt.
  341.   *)
  342.  traise("sig=SIGUSR1", FALSE, SIGUSR1);
  343.  
  344.  (* Blockierung fuer SIGUSR1 aufheben, Signal muss jetzt gesendet werden *)
  345.  handled := FALSE;
  346.  save    := sigsetmask(save);
  347.  IF NOT handled THEN
  348.    WriteString("*** Signal not handled");
  349.  ELSE
  350.    WriteString("Signal handled OK");
  351.  END;
  352.  WriteLn;
  353.  
  354.  (* 'handler2' als Signalhandler fuer SIGUSR1 installieren. Der alte Handler
  355.   * muss 'handler1' sein.
  356.   *)
  357.  newh.proc := handler2;
  358.  oldh.proc := handler1;
  359.  tsignal("sig=SIGUSR1 new=handler2 old=handler1)", SIGUSR1, newh, oldh);
  360.  
  361.  (* Die Signalmaske beim "sigsetjmp()" sichern. SIGUSR1 synchron ausloesen.
  362.   * Mit "siglongjmp()" den Signalhandler verlassen.
  363.   *)
  364.  traisejump("sig=SIGUSR1 savemask=TRUE", SIGUSR1, TRUE);
  365.  
  366.  (* Die Signalmaske beim "sigsetjmp()" nicht sichern. SIGUSR1 synchron
  367.   * ausloesen. Mit "siglongjmp()" den Signalhandler verlassen.
  368.   *)
  369.  traisejump("sig=SIGUSR1 savemask=FALSE", SIGUSR1, FALSE);
  370.  WriteLn;
  371.  
  372.  
  373.  (* Defaultaktion fuer SIGUSR1 installieren, der alte Handler muss
  374.   * 'handler2' sein.
  375.   *)
  376.  WITH new DO
  377.    saHandler.long := SigDfl;
  378.    sigemptyset(saMask);
  379.    saFlags := SaFlags{};
  380.  END;
  381.  WITH old DO
  382.    saHandler.proc := handler2;
  383.    sigemptyset(saMask);
  384.    saFlags := SaFlags{};
  385.  END;
  386.  tsigaction("sig=SIGUSR1 new=SIG_DFL,mask={} old=handler2,mask={}",
  387.             SIGUSR1, new, old);
  388.  
  389.  
  390.  (* 'handler3' als Signalhandler fuer SIGUSR1 installieren. Innerhalb
  391.   * des Handlers soll zusaetzlich zu SIGUSR1 auch noch SIGUSR2 blockiert
  392.   * sein. Der alte Handler muss die Defaultaktion sein.
  393.   *)
  394.  WITH new DO
  395.    saHandler.proc := handler3;
  396.    sigemptyset(saMask);
  397.    void := sigaddset(saMask, SIGUSR2);
  398.    saFlags := SaFlags{};
  399.  END;
  400.  WITH old DO
  401.    saHandler.long := SigDfl;
  402.    sigemptyset(saMask);
  403.    saFlags := SaFlags{};
  404.  END;
  405.  tsigaction("sig=SIGUSR1 new=handler3,mask={SIGUSR2} old=SIG_DFL,mask={}",
  406.             SIGUSR1, new, old);
  407.  
  408.  
  409.  (* Die Signalmaske beim "sigsetjmp()" sichern. SIGUSR1 synchron ausloesen.
  410.   * Mit "siglongjmp()" den Signalhandler verlassen. Nach Verlassen des
  411.   * Handlers muss die Signalmaske wieder den Wert vor dem "sigsetjmp()" haben,
  412.   * hier also leer sein.
  413.   *)
  414.  traisejump("sig=SIGUSR1 savemask=TRUE", SIGUSR1, TRUE);
  415.  tsigprocmask(SigSetMask, NULL, ADR(newm.sigset));
  416.  sigemptyset(oldm.sigset);
  417.  IF oldm.siglong = newm.siglong THEN
  418.    WriteString("sigprocmask: signal mask OK");
  419.  ELSE
  420.    WriteString("*** sigprocmask: unexpected signal mask");
  421.  END;
  422.  WriteLn;
  423.  
  424.  (* Die Signalmaske beim "sigsetjmp()" nicht sichern. SIGUSR1 synchron
  425.   * ausloesen. Mit "siglongjmp()" den Signalhandler verlassen. Nach Verlassen
  426.   * des Handlers muss die Signalmaske mindestens SIGUSR2 enthalten (und SIGUSR1
  427.   * unter TOS).
  428.   *)
  429.  traisejump("sig=SIGUSR1 savemask=FALSE", SIGUSR1, FALSE);
  430.  tsigprocmask(SigSetMask, NULL, ADR(newm.sigset));
  431.  IF sigismember(newm.sigset, SIGUSR2) > 0 THEN
  432.    WriteString("sigprocmask: signal mask OK");
  433.  ELSE
  434.    WriteString("*** sigprocmask: unexpected signal mask");
  435.  END;
  436.  WriteLn;
  437.  
  438.  Read(c);
  439. END tsighandler.
  440.