* more patches (for Unix signal mask) @ 1999-05-16 21:40 Joerg Czeranski 1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski ` (2 more replies) 0 siblings, 3 replies; 7+ messages in thread From: Joerg Czeranski @ 1999-05-16 21:40 UTC (permalink / raw) To: caml-list Hi! I had a look at the web interface to Caml's CVS repository and noticed that my previous patches are already incorporated (except for byterun/intern.c, but I'm not so sure that it makes a difference at all). :-) The DEC/Compaq C compiler people acknowledged that the sigsetjmp() handling in byterun/interp.c is a bug and they promised to fix it in a later compiler version. Now for my new O'Caml problems: An exception raised from C code (e.g. in the Unix module for every system call error) resets the current signal mask - by calling siglongjmp() in the bytecode interpreter or in default_reset_sigmask() for native binaries. I'm porting a small shell to O'Caml and it's mandatory that SIGCHLD stays blocked while process group data structures are modified, because the SIGCHLD handler has to modify them, too. I replaced all sigsetjmp() calls with _setjmp() calls (setjmp() is allowed to modify the signal mask, too, as per Single Unix Spec v2) and handled jumps out of signal handlers separately. Tracing the resulting binaries for the 2*3 cases that I know - raise in Caml code vs. raise in C code and raise without signal handlers vs. raise out of asynchronously handled signal vs. raise out of synchronously handled signal - seems to indicate that signal masks retain their proper values. sigaction() calls with SA_NODEFER and/or non-empty sa_mask fields are not yet handled, but they're not supported in O'Caml 2.02's Sys module anyway. The Single Unix Spec advises against using _setjmp() and for using sigsetjmp(), but I don't know how that could work without mistreating the signal mask in O'Caml. joerch ==================== patches ==================== *** byterun/interp.c.orig Mon Mar 15 16:07:12 1999 --- byterun/interp.c Sun May 16 22:23:02 1999 *************** *** 201,207 **** initial_external_raise = external_raise; callback_depth++; ! if (sigsetjmp(raise_buf.buf, 1)) { local_roots = initial_local_roots; accu = exn_bucket; goto raise_exception; --- 201,207 ---- initial_external_raise = external_raise; callback_depth++; ! if (_setjmp(raise_buf.buf)) { local_roots = initial_local_roots; accu = exn_bucket; goto raise_exception; *** byterun/fail.h.orig Fri Nov 20 16:36:26 1998 --- byterun/fail.h Sun May 16 00:31:31 1999 *************** *** 30,46 **** #define STACK_OVERFLOW_EXN 8 /* "Stack_overflow" */ #define SYS_BLOCKED_IO 9 /* "Sys_blocked_io" */ - #ifdef POSIX_SIGNALS struct longjmp_buffer { - sigjmp_buf buf; - }; - #else - struct longjmp_buffer { jmp_buf buf; }; - #define sigsetjmp(buf,save) setjmp(buf) - #define siglongjmp(buf,val) longjmp(buf,val) - #endif extern struct longjmp_buffer * external_raise; extern value exn_bucket; --- 30,38 ---- *** byterun/fail.c.orig Sun Feb 14 17:48:22 1999 --- byterun/fail.c Sun May 16 01:13:01 1999 *************** *** 32,38 **** Unlock_exn(); exn_bucket = v; if (external_raise == NULL) fatal_uncaught_exception(v); ! siglongjmp(external_raise->buf, 1); } void raise_constant(value tag) --- 32,38 ---- Unlock_exn(); exn_bucket = v; if (external_raise == NULL) fatal_uncaught_exception(v); ! _longjmp(external_raise->buf, 1); } void raise_constant(value tag) *** byterun/debugger.c.orig Tue Sep 2 14:53:57 1997 --- byterun/debugger.c Sun May 16 01:13:37 1999 *************** *** 149,155 **** /* Catch exceptions raised by output_val */ saved_external_raise = external_raise; ! if (sigsetjmp(raise_buf.buf, 1) == 0) { external_raise = &raise_buf; output_val(chan, val, Val_unit); } else { --- 149,155 ---- /* Catch exceptions raised by output_val */ saved_external_raise = external_raise; ! if (_setjmp(raise_buf.buf) == 0) { external_raise = &raise_buf; output_val(chan, val, Val_unit); } else { *** byterun/signals.c.orig Mon Oct 26 20:18:04 1998 --- byterun/signals.c Sun May 16 01:13:49 1999 *************** *** 45,53 **** #endif #endif if (async_signal_mode){ ! leave_blocking_section (); ! execute_signal(signal_number); ! enter_blocking_section (); }else{ pending_signal = signal_number; something_to_do = 1; --- 45,76 ---- #endif #endif if (async_signal_mode){ ! if (external_raise == NULL) { ! leave_blocking_section (); ! execute_signal(signal_number); ! enter_blocking_section (); ! } else { ! struct longjmp_buffer raise_buf, *saved_external_raise; ! ! saved_external_raise = external_raise; ! if (_setjmp(raise_buf.buf)) ! { ! sigset_t s; ! ! external_raise = saved_external_raise; ! sigemptyset(&s); ! sigaddset(&s, signal_number); ! sigprocmask(SIG_UNBLOCK, &s, NULL); ! _longjmp(external_raise->buf, 1); ! } ! else ! { ! external_raise = &raise_buf; ! leave_blocking_section (); ! execute_signal(signal_number); ! enter_blocking_section (); ! } ! } }else{ pending_signal = signal_number; something_to_do = 1; *** asmrun/stack.h.orig Wed Nov 18 19:10:52 1998 --- asmrun/stack.h Sun May 16 02:31:25 1999 *************** *** 85,89 **** --- 85,95 ---- extern value caml_globals[]; extern long * caml_frametable[]; + struct caml_sigblock_node { + struct caml_sigblock_node *next; + int signal_number; + }; + + extern struct caml_sigblock_node *caml_sigblock_stack; #endif /* _stack_ */ *** asmrun/fail.c.orig Thu Nov 26 11:00:51 1998 --- asmrun/fail.c Sun May 16 02:48:11 1999 *************** *** 36,41 **** --- 36,42 ---- static void default_reset_sigmask(void) { + #if 0 #ifdef POSIX_SIGNALS sigset_t mask; sigemptyset(&mask); *************** *** 45,50 **** --- 46,52 ---- sigsetmask(0); #endif #endif + #endif } void (*caml_reset_sigmask)(void) = default_reset_sigmask; *************** *** 55,66 **** --- 57,79 ---- char * caml_exception_pointer = NULL; + struct caml_sigblock_node *caml_sigblock_stack = NULL; + + void mlraise(value v) { + sigset_t s; + int do_unblock; + struct caml_sigblock_node *stack; + (*caml_reset_sigmask)(); Unlock_exn(); if (caml_exception_pointer == NULL) fatal_uncaught_exception(v); + sigemptyset(&s); + do_unblock = 0; + stack = caml_sigblock_stack; + #ifndef Stack_grows_upwards #define PUSHED_AFTER < #else *************** *** 70,76 **** --- 83,102 ---- (char *) local_roots PUSHED_AFTER caml_exception_pointer) { local_roots = local_roots->next; } + + while (stack != NULL && + (char *)stack PUSHED_AFTER caml_exception_pointer) { + sigaddset(&s, stack->signal_number); + do_unblock = 1; + stack = stack->next; + } #undef PUSHED_AFTER + + if (do_unblock) + { + sigprocmask(SIG_UNBLOCK, &s, NULL); + caml_sigblock_stack = stack; + } raise_caml_exception(v); } *** asmrun/signals.c.orig Thu Nov 26 11:08:37 1998 --- asmrun/signals.c Sun May 16 02:39:14 1999 *************** *** 115,123 **** --- 115,131 ---- if (async_signal_mode) { /* We are interrupting a C function blocked on I/O. Callback the Caml code immediately. */ + struct caml_sigblock_node sigblock_node; + + sigblock_node.next = caml_sigblock_stack; + sigblock_node.signal_number = sig; + caml_sigblock_stack = &sigblock_node; + leave_blocking_section(); callback(Field(signal_handlers, sig), Val_int(sig)); enter_blocking_section(); + + caml_sigblock_stack = sigblock_node.next; } else { /* We can't execute the signal code immediately. Instead, we remember the signal and play with the allocation limit ==================== end of patches ==================== ^ permalink raw reply [flat|nested] 7+ messages in thread
* Are exceptions evil? (was: more patches) 1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski @ 1999-05-17 11:03 ` Joerg Czeranski 1999-05-18 1:25 ` UPDATE: more patches Joerg Czeranski 1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy 2 siblings, 0 replies; 7+ messages in thread From: Joerg Czeranski @ 1999-05-17 11:03 UTC (permalink / raw) To: caml-list This morning I rethought my patches under the shower and found another bug (signals are not blocked while the handler is executed, if the signal was caught with async_signal_mode == 0). It's not difficult to fix, I'll do that later. Even the signal loss race condition can be fixed without too much thought. But that's because signals are easy to control, they move down the stack (for stacks growing down). They won't bypass interrupted functions, they only return to them after being handled. Exceptions on the other hand go straight up the stack until they find a handler, and then *immediately* invalidate the handler. In a non-pure programming language like O'Caml this creates unavoidable race conditions: let resource = acquire () in try use resource; release resource with e -> release resource; raise e "release" is never called if two exceptions arrive at virtually the same time, and neither if an exception arrives after the call to "acquire", but before the "try". N.b.: For me acquire is usually Unix.openfile, but it could as well be a native O'Caml function with sideeffects (like "incr semaphore"). I think the fundamental reason for this problem is that exceptions are thrown up the stack and not forward on the timeline of side effects. They ought to skip new acquire calls, but never a release call for a resource already acquired. Is there anything that can be done about this? Or does it require wrapping all (relevant) side effects with monads? Or am I missing something? regards, joerch ^ permalink raw reply [flat|nested] 7+ messages in thread
* UPDATE: more patches 1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski 1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski @ 1999-05-18 1:25 ` Joerg Czeranski 1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy 2 siblings, 0 replies; 7+ messages in thread From: Joerg Czeranski @ 1999-05-18 1:25 UTC (permalink / raw) To: caml-list Hi, my previous patch still left a lot of race conditions, and it didn't do anything to avoid signal loss - O'Caml 2.02 only queues one signal and forgets all others until a handler is called. I think these patches (to be applied on top of the previous) should fix both of the problems. It can also easily be extended to handle a per-signal sa_mask (see the sigaction man page). It requires Unix signals though. As I have neither NT nor a Mac, I couldn't test it on any non-Unix system. Testing is rather difficult anyway, as some cases only happen when multiple signals arrive at almost the same time. Therefor there are probably still a few bugs lurking there. As it's almost a complete rewrite of the signal stuff, I'll gnuzip and uuencode the patches this time. :-) These files are affected by the patches: otherlibs/unix/signals.c byterun/signals.h byterun/signals.c byterun/interp.c asmrun/fail.c asmrun/signals.c joerch begin 644 patch.03.gz M'XL(```````"`^T<:W/;-O)S_"M@MY-*-B63E&3K46<N[:4]3Q.G4R?7F^ED M.#`%26PH4B4IVVKJ_WZ[`$B")*A'G-S%:32.(X*+Q6)?V%UL\H_&5\T%3=Q9 MV^P\LMI=TCNV^L>#P=[AX2$)DQF+?.\J/EX&WNUQ[$T#ZL=MMQU&WO31BS`@ M+]V$V"?$-H?68&CVB348]/=:K5;M5#[K!5T1ZQ1^AB9,/,%9?$'UPPFP;`/@ M^",BQ<<^@6^M/4*.#\G7Y^,AR5`;U\1J=S@)QY9Y;"->2=8X]+TI^Y,\NUV0 MK\GA,4R'GZ^\P/678T:^95$4A.W9D[TC93!.(B^8PB@N-0DC,F=S=[$2TQ4P MOCY.+B&EOA^Z.*[;6>_4.+'SG?7ZQFDOW1DAL_"&G.'.%E'HSFG\UG'GX]_. M@\2YIG[CFKJ)%P;--R,./&9N.&8.0,<L:5S#+X,\AM]-\=J;D(:"J0&XQ7OX M'?IC!"1G9Z1E-<D2^!!&C0,%_,`@%R!+8`2@.R+P(S`BA?MGY/+\1^?RV:L7 M3R]_:O)W[_AO+IT)`[4BH`<D8#<$D2'KQ&M8@<T7R0HIEK2*%V5J<8'OGK_\ M_J>,9H5@.8=L03@A=RGY0%K"?)]3)H1'9C08^P!*D),IE<O%F":<KP#B<&HR M4CEG(Y8LHX"P0.5_RE-D_AVJ!$K[:I6P:!ED9C`3%O1JMB1/EU-B==`6>OVA M>9I;4&6.:CJV/>R=##OF&M/I&AVI8*B4DV#,)D1N)G9P#`:\@!7&5/T]F'LQ MJ.]!<<P'!5RR6(S##[L%*@/"1R4W'<Y-%L6CO?WL?>C3Q/,9\8*$+%@P!F;+ MA>N@XG#.N/R<)'3&X4A93`4#PW092.?W,')BWW-9'3X:KP(WDR9(;"1V<!UZ M8Y`A3'"NP&#?<LH8MS#2P)=<E!S*9_2:;81:1M,"0<I[I,,-@VL6)2DEP7)^ MQ2+2@%?-49&GB*QQJ"?-F87AVV:C.:K`ZXG,X;DC!>4X3=W-ULIQI/-Z:$X1 M^V/I16S,O22\<6@2SCW7280I?7RM*JQ)4]9ZL2-5;>.<#ZEL16(>@M8=2105 MA\=],7@SE&0.-X4!=QE%0/YF8"$VIVCSL4+=1U=XG0.&$,8?/WH%VL4=:I^8 MUM`^'79[PJ'J_*];`+<1O'/Z(4,7VRS'+G`@=#?&+GG\L7OP<B!CE*(YNC!Z M1=VWE?$PF'A3'-5MV.X873,_<-))V?%5Q!6O4FO?W^"F(1`R1V6HHCII04HF M+6#(!GO.H'2>)T>QA9X"\,7KY\\5^/5ZJL##3N($B'2EE[AE[C*SRP;?FVK% MS3T,NS`@>1K'8..DL5]AHHP%4\DV?O"8/VZ4]F>4\!KDW^A%@Z11',]C&U*P M\7H"T0+LKF&!BF>'S@X*`BI\'ES3R*-!,B2_SE!\@BL8LWU/YSX/W`RB]4H0 M4E(_8G2\`E2$RQ9<#_%B&+ZAJU@$@G3.0/?X=PBOEZ!4KR%Q20-$Q-06T\O+ MXPQ.@AI+@F^59R$.74`LBNN!<P2U$VATI,),>,\QEA<W^$L*T>:MRQ:H.`)- MNAI@]P+0&M^'8SB94?#XH&^@LQ>(\0HB88XFQDV`#]A'MJ8'_P4$V?@HSWQ\ M)!T;1]#*)@)XR^.M8HH%\-(I\!LN]6:$\O4"+_%`,'\B^2$Q!9%;'_#KE_T< M7$%VMFH49Y2#\;.^"N%PI4^YQ!FE/?"5(QP?A6N12=,X#+X!YL.)<4,B"@R" M\V#L\5@$?G3ZS`^;#6X)D8NSJ?%8@\.0VA^#9H03W2H2Q[I-6P@B\S_5L^9* M5^`!#TT`]%V6[>[78F]F&6_&.?B=I<IK,EU4^HF:XY,)]7QPPC>,+""U!,5& M2YB!IG"[1R2J1R@DTQORY73-=2FMR)`EE];%>14=R3BE9V=1R$*<>E%+(1]F M8M7(;--I:'`3\(+45'/R("1:N@GQPV#Z^WSA7"TG$W"<$?5BA@\&.8R!UV-' M1)>`D+\:R:T!SDRJ&Q5Z'2<X0*T+PY=E+UG8WYL<#D^8AL?UFWCD6^ZXX=O1 M45,III21>6_2M^^R\HF>&FN4`5S!\?DV?<P**3IVP3PM_X"2$N"^\'*Y`2$, MN,($A-/(I-*&/\VF0BN8#1@(C1C!0(9<>Y0X4J3@.3.;X%8Q9CXWNQIE4T.4 MD3JO8$VRO%6GLWP/BKT34F%(O5KA)Z.^"-!ZPG72RBB[([B;^E4>9SPKU;N` M7#H>[\:(]V;"!XTR\PWL+,GLO(H81EU*K8_[3M"U&_9-Q-)P2Q('N$+U.>7V M.&0Q(@M8G)!E$#"7Q3'$H_XJU3A^2A2]SKV5:4M%VC$6U^5NW9YQVL]R-Q'U M*5_$]JK.[IV(0776?99;][[4V+HZ1G.4@92<>UFP&5A-W20#$;:BK/V^OI_' M2A+%=MXN!5_CS3(8I.]1'C?(Y1YM*7<Q5PDNFNE8:NYQU38$0$$G7U]D`4.F M@0"VV2^EV[C+!8,>JK"[M6XJA=Q*-[;6CBWT(Z?YCJOW'1*>:DNEME!82"32 M1)-36.+5'3=(4?/I&5;G)$MY=[:KC5Q9QQ&0D4BLLASQ\#B?6,^A"C]JHP,= MNS31BK4ERW2.J=\Q+#.K*M6BN$L+2;5%51G4$^D3T"\F8#JR`$G(#<_J&U;S MG21V;8RWGX8BYQ-"TX.%1I%WS6)RQ9(;Q@)Y\W4+"]V$/#E'%P2DQ$:NJEY" M;CS?ASG@F^*D+=)>_"!UL+W278E./<V1XH9Q6K.L%WPPE8(N9;=4%/O%%9II M]%<_W<S%*`^#^GPXC_O6`.7W%)9AG2@7HUO(7U]PULC?&XE+C8WQ_.:(_9Z1 M>,60/8.8J%Y!F%0,N)BCK=7V(UD7?!_EKF'C#FJDX=C_2Y>T!?H^>.=!-_<M MV84N$A1F:M4JULE:E3I9*W7H+9*5BV0MSBG&OHU"+2EUTV)0WNFCU%\\%Y43 M(2T9P@F#L'NF8?>D06AW->@;MMG)+Q[LWL"P3ZJ'4$HIQ,>9':Q-6V4X"R+2 MWB4UTNX$3:TXN]8'TS#)7W]Q/$_..`>;1#+?"WA!Q:'1=#D'>38.+E=Q6V`; M0M!-KZGGTRL_Y=]!C5QMNV/8]B"7ZYVXXT0)_OSR\OP_#JQZ\?3Y9;HCX'P[ MIJF,8'\P(!2Y&%YED+(\49P^\>DTSO57;EA(%;]A>,6?9=L%_YYU7L2KV!$] M#!<OG:>__"C1`R!``=9LAD*IU(C^B6$/%!?Y_ML%U>,6A#4^T<"3WE`9XO$& M0SC(ON?>=(;!-#R%8`CAA,R7?N(M_"SX2Z_Y>"5:'(SDCZ7GOH6,Z<9+9CK3 M!_^!1>X413*+PIN\W!VG1R/,F<"1^:G*1+UM]-`K+>1EH]KXU!O:_6&O7[UL M3&<4>CW,H=D9]@;U=XVG`]/H6Y;JRO`S]X(P<MS0]TOAG?C\`LEL&#&'3M!W M3MW\71[0;Q'B3$*L"/.;D/HX9UVD`XZ.5/+4:NBC(*L/@10Q*TY(203EIGY> MQJ"#J<.?1'C[DXC47R;FHA4(S(%RUBG4<AU;D-89Z8Y*@[^9&/#JZQD56`MA MQ9'0)`NW\M[&]RRXKKSHI(M@AH;I6431:\:E)6";WT4TP!ZLL-+LQ*.)`CBL M!&BW*MD4UUFX,.][;(%"]P]H2N]S`LN2NMM3OX'3(G/J`N?">+:G2A-KX!CP M<>M`$WW'C0;5_G0PR%W?!U-[GI9IPA=5CRY!=Q8.1'X<1SY>U_!0X,HZ(G;D M!#H`&L_1>^`%0M7;@/_`7@7%VQ3`RVUEG6&GM\;5`,M/<D?S.L`#PV&W04,Y MZ5TZ]YW,<SN+D).;UX0F%((C9QFX=`D'20[9N&[*2Z_RV2N1CT.8)<ZHS*M# MH,4?^:(PB[]V^"A'QC6%4YWIR<>CNN[*Y%X[T";&)\8@:^]3@WR!3`;&Y/%C M1?-ABS,*=M\4,#^_OOS7LW\Z3W]X]>P7HM]\[CE+525$T'I2]@IIL5398I[\ MRTW*J9@8IY$^2DCL1TKH?[.?M*;\P?>CD]>@JQ8R,IW+<3?WTIJ9KFZLJ]$) M.C1*DU*59U*<Q9P$J\#C74C(2]=JF;#V5G%'`A4O5NS1VL:1:;O+T9?UUW:7 M=TSCI*OI6$HTO4\?H5_I830@\#CBF2A/Y(%@UG8RG[.Q!]+W5VW9F_:`FI=@ M9Z]F7DRB$%MY&#;1\`@PG,]#[.M.HA7AGH,7>*8TNJ)3?)U&%D+#L3&GW$>> MMNF)>W0Q40E)E&I4JY#BYV:Y"I<@F$420<XLO@-;@3^0/5<TI5F)>7@![?[Q M>ZL^=F]EY8!RG-ZJB=`1D]B)[\T]S*"4?0E?(D/WIJ:P799;Y$VGH(!4(Q;L MXXI#\?<BC&,/BP9(,G@,L'FKT]%TH6TR^L^N6>IAN)^C[?J?CG;H?\J+IUOT M/QW=L__IZ$O_TY?^I_OU/WWD$[C:,$6*#5/%`"Y`OU5X*G=(D2\=4DKG2LZG M-K\,K$GSJM#E<ECI%OJH-K1^7)'.ES:@A]P&5)-`550K"Y".MK@(S7W6#HV- MG^1%Z*<1QG^XL'V+,'G=W>S]0F1MR:]7+#5MUV6ARVMVNX=NW;/)HK7NZJ%% MR-H$ICZ%V2B=S6G,PVO#Z!I6KZ>4CK;3@=UEOB6#/__F!)ZGGJ@W>F`(OX() M4SR`I%ZIYQF_KE*#P;Q0>@YFP>B81]81@S@4`PIE*GJ^A4_ES2S_%U!^=O'% MI9#CX@<C37*[4T"YD25KO(YRZ:=KLELG?@`?Y8RX#.>0)(11$@-#7"!%G0+G M!-[L33W8=:2PX75<8AB(!1U'2$"ZWF0E-I9.A/'0(%?+1)P]$V$(@XYAFZ9Z MX_1YB67W7K]"A]^G*3G]OU;M&G:W\PEW_VS\B&,66T`&?:-C=NJ;@NQNW[![ M2E-0QX095N]OU!1T"H9[^K=I"NIT>D:G:W_<IB"T/RK^AP*((!](>\Y_`5;T &HJSP2``` ` end ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: more patches (for Unix signal mask) 1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski 1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski 1999-05-18 1:25 ` UPDATE: more patches Joerg Czeranski @ 1999-05-18 16:10 ` Xavier Leroy 1999-05-19 18:32 ` Joerg Czeranski 2 siblings, 1 reply; 7+ messages in thread From: Xavier Leroy @ 1999-05-18 16:10 UTC (permalink / raw) To: Joerg Czeranski; +Cc: caml-list > I had a look at the web interface to Caml's CVS repository > and noticed that my previous patches are already incorporated > (except for byterun/intern.c, but I'm not so sure that it makes > a difference at all). :-) I'm still not sure whether the casts are really needed or whether the Dec C compiler is wrong in emitting a warning. > I replaced all sigsetjmp() calls with _setjmp() calls (setjmp() is > allowed to modify the signal mask, too, as per Single Unix Spec v2) > and handled jumps out of signal handlers separately. That's an interesting idea; I'll have to think about it. By the way, you can just do sigsetjmp(..., 0) if you don't want the signal mask to be saved and restored; this is more portable than _setjmp. > Exceptions on the other hand go straight up the stack until they find > a handler, and then *immediately* invalidate the handler. > In a non-pure programming language like O'Caml this creates unavoidable > race conditions: > let resource = acquire () in > try > use resource; > release resource > with e -> > release resource; > raise e > "release" is never called if two exceptions arrive at virtually > the same time, and neither if an exception arrives after the call > to "acquire", but before the "try". Yes, asynchronous exceptions (such as those generated from a signal handler) are very hard to use because of this. The programming idiom you showed above is safe for synchronous exceptions (exceptions that can only be raised by "use resource"), however. My take on this is that exceptions as they are implemented now are just fine as a non-local control structure inside a sequential program, but that something else is needed for multithreaded and signal-based processing. The thread cancellation model of Posix threads is an interesting example of how inter-thread asynchronous notifications can be made safe. Regards, - Xavier Leroy ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: more patches (for Unix signal mask) 1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy @ 1999-05-19 18:32 ` Joerg Czeranski 1999-05-25 15:16 ` John Skaller 0 siblings, 1 reply; 7+ messages in thread From: Joerg Czeranski @ 1999-05-19 18:32 UTC (permalink / raw) To: Xavier Leroy; +Cc: caml-list Xavier Leroy answered to my mail: > > I replaced all sigsetjmp() calls with _setjmp() calls (setjmp() is > > allowed to modify the signal mask, too, as per Single Unix Spec v2) > > and handled jumps out of signal handlers separately. > > That's an interesting idea; I'll have to think about it. By the way, > you can just do sigsetjmp(..., 0) if you don't want the signal mask to > be saved and restored; this is more portable than _setjmp. Ah, I missed that in the man page, I'll have a look if it has no unexpected side effects ;-) to use sigsetjmp(..., 0). > > Exceptions on the other hand go straight up the stack until they find > > a handler, and then *immediately* invalidate the handler. > > In a non-pure programming language like O'Caml this creates unavoidable > > race conditions: > > let resource = acquire () in > > try > > use resource; > > release resource > > with e -> > > release resource; > > raise e > > "release" is never called if two exceptions arrive at virtually > > the same time, and neither if an exception arrives after the call > > to "acquire", but before the "try". > > Yes, asynchronous exceptions (such as those generated from a signal > handler) are very hard to use because of this. The programming idiom > you showed above is safe for synchronous exceptions (exceptions that > can only be raised by "use resource"), however. What about resource problems like stack overflows and running out of heap memory? I think they might happen at the call to "release". But it probably depends on the interna of the release function. > My take on this is that exceptions as they are implemented now are > just fine as a non-local control structure inside a sequential > program, but that something else is needed for multithreaded and > signal-based processing. The thread cancellation model of Posix threads > is an interesting example of how inter-thread asynchronous > notifications can be made safe. Maybe signals should be handled in a completely different way, not via handlers, but as a special kind of input stream. A function similar to Unix.select (even a wrapper around it) could provide signal notification service. Such a model might be useful for C programs too. I never got around to trying this idea though. Maybe I'll try to write such a function for O'Caml as an alternative to the Sys.signal facility. joerch ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: more patches (for Unix signal mask) 1999-05-19 18:32 ` Joerg Czeranski @ 1999-05-25 15:16 ` John Skaller 1999-05-27 19:10 ` Xavier Leroy 0 siblings, 1 reply; 7+ messages in thread From: John Skaller @ 1999-05-25 15:16 UTC (permalink / raw) To: caml-list At 20:32 19/05/99 +0200, Joerg Czeranski wrote: >Maybe signals should be handled in a completely different way, >not via handlers, but as a special kind of input stream. Synchronous exceptions present enough difficulties without asychronous ones. A possible systemic difference is that while it is common to make synchronous exceptions equivalent to non-local gotos, that is, there's no retry, asynchronous exceptions should probably permit continuation. For example, after a keyboard interrupt, it often makes sense to complete some part of the current processing before responding; so the signal handler could set a flag which is polled at an appropriate place. So it is my guess that when a synchronous exception occurs, the stack should be unwound up to the handler, but for an asynchronous exception, the handler is invoked _without_ unwinding the stack. The handler has the choice os unwinding the stack, and thus making the signal act like a synchronous exception, or, continuing with the interrupted processing after changing state local to the handler which will cause a defered response to the signal, again synchronising the asynchronous event. In other words, no program can handle asynchonous events, they have to be synchonised with the normal control flow somehow, and the purpose of an asynchronous signal handling mechanism is to provide a choice of alternatives. We probably need the reverse too: a way to generate asynchronous exceptions. For example, a file operation which fails due to a hardware error which is reported with an error code could lead to generation of an asynchronous exception which is not normally caught an exception handler. Local synchronous handlers can be designed to handle end-of-file conditions, but hardware errors might require a different kind of processing, such as 'Please put the CD-ROM back in the drive!!' :-) ------------------------------------------------------- John Skaller email: skaller@maxtal.com.au http://www.maxtal.com.au/~skaller phone: 61-2-96600850 snail: 10/1 Toxteth Rd, Glebe NSW 2037, Australia ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: more patches (for Unix signal mask) 1999-05-25 15:16 ` John Skaller @ 1999-05-27 19:10 ` Xavier Leroy 0 siblings, 0 replies; 7+ messages in thread From: Xavier Leroy @ 1999-05-27 19:10 UTC (permalink / raw) To: John Skaller, caml-list > Synchronous exceptions present enough difficulties without > asychronous ones. A possible systemic difference is that > while it is common to make synchronous exceptions equivalent > to non-local gotos, that is, there's no retry, asynchronous exceptions > should probably permit continuation. Actually, that's how signal handlers work in Caml (like in C): a user-specified function is called at the earliest possible moment. However, that function may choose to raise an exception (that's what I called and asynchronous exception), and that's where the problems Joerg mentioned occur. - Xavier Leroy ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~1999-05-28 15:06 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1999-05-16 21:40 more patches (for Unix signal mask) Joerg Czeranski 1999-05-17 11:03 ` Are exceptions evil? (was: more patches) Joerg Czeranski 1999-05-18 1:25 ` UPDATE: more patches Joerg Czeranski 1999-05-18 16:10 ` more patches (for Unix signal mask) Xavier Leroy 1999-05-19 18:32 ` Joerg Czeranski 1999-05-25 15:16 ` John Skaller 1999-05-27 19:10 ` Xavier Leroy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox