Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!newstop!texsun!convex!news From: tchrist@convex.COM (Tom Christiansen) Newsgroups: comp.lang.perl Subject: Re: Signal handlers, scoping & control confusion Message-ID: <1991Mar06.231111.23553@convex.com> Date: 6 Mar 91 23:11:11 GMT References: Sender: news@convex.com (news access account) Reply-To: tchrist@convex.COM (Tom Christiansen) Organization: CONVEX Software Development, Richardson, TX Lines: 123 Nntp-Posting-Host: pixel.convex.com From the keyboard of lgy@phys.washington.edu (Laurence G. Yaffe): :After reading 'the Book' & scanning the man page, I'm still confused about :signal handlers & scoping rules for things like statement labels & :subroutine names. As an example, consider a structure like: [ i reformatted this for personal legibility --tom] sub foo { loop: foreach $file (...) { $SIG {'INT'} = 'interrupt' ; &compare (...) ; sub interrupt { last loop if (...) ; } } # end foreach return; } sub compare { if (...) { &interrupt ; } } :(a) The 'last loop' statement inside the handler 'interrupt' does seem : to work. If I omit the statement label on the 'last' statement inside : the handler, then perl occasionally dumps core (this is at PL37). : Should a label-less 'last', 'redo', etc. statement inside a : nested subroutine work? It's a shock to me that any of them work. There's another thread around here talking about it. I don't think that a next/last/redo should look up through your callstack to find a loop. If there's not one in the current subr, I think you should be out of luck. : Even if the subroutine is a signal handler? Signal handlers have a slightly different context than normal subroutines -- notice how caller() doesn't work right with them. : What determines if a statement label is in scope - : lexical (static) scoping or dynamic scoping? I always thought that labels were lexically scoped. If Larry lets this current obfuscation of nexting up through subs work, then I guess it would have to be dynamic. :(b) Calling the 'interrupt' from within the 'compare' routine works. : Should it? Although this is very convenient for my purposes, : I would have expected 'interrupt' not to be in scope within the : 'compare' routine. I think you're making a bad assumption here. Subroutine declarations do not nest as they do in Pascal. No matter where it appears, a subroutine declaration will be globally visible for the whole package. It is not like local()s, which provide for dynamic scoping. As for calling interrupt from within your &compare function, this too is relying on the weird lasting out of a subroutine behavior. You don't need to set $SIG{'INT'} at every loop iteration. You're not declaring it to be of local scope or anything that way. That handler will be in effect forever that way. Either reset it, or declare it local: { local($SIG{'INT'}) = 'interrupt'; Signal handlers are global unless localized. It looks very much like you're trying to do some exception handling here. In perl, you want to use an eval and a die for such things. May I suggest using die/eval, which is perl's mechanism for this? Something like this: sub interrupt { die 'Interrupted'; } sub foo { local ( $SIG{'INT'} ) = 'interrupt'; LOOP: foreach $file (...) { &compare (...) ; .... } # end foreach .... } sub compare { die "Bad compare" if (...); .... } Now having set if up like this, you call your foo function in an eval, to trap the dies and see what they were. (die == raise, eval == catch): eval '&foo'; if ($@) { # caught an exception if ($@ =~ /interrupted/i) { warn "interrupted, continuing"; } elsif ( $@ =~ /bad compare/i) { warn "bad compare, continuing"; } else { die $@; } } Notice I don't call exit even if it's something I don't expect. I re-raise the exception so someone higher up can catch me if he wants. --tom -- I get so tired of utilities with arbitrary, undocumented, compiled-in limits. Don't you? Tom Christiansen tchrist@convex.com convex!tchrist