/* finish on-unit for PL/I symbolic debugger called from debmain */ debfinish: procedure; %include 'putdef.pli'; %include 'workdef.pli'; %include 'brksymdef.pli'; %include 'knldef.pli'; %include 'exitdef.pli'; %include 'initdef.pli'; %include 'truefalse.inc'; dcl mark entry(fixed bin(15), fixed bin(15), fixed bin(15), fixed bin(15)); /*from PLIUTL*/ dcl canmt entry(fixed bin(15), fixed bin(15)); /*from PLIUTL*/ dcl readef entry(fixed bin(15)) returns(fixed bin(15)); /*from PLIMMR (not the one in PLIUTL)*/ dcl (no_error, not_active, io_det) fixed bin(15) external; /*defined in debasm*/ dcl (exit_event, time_event, mcr_event) fixed bin(15) external; /*defined in debmain*/ dcl delay_event fixed bin(15); delay_event=mcr_event; dcl (dsw, mark_dsw) fixed bin(15), abort_not_complete fixed bin(1); mark_time: procedure(event, seconds); dcl (event, seconds) fixed bin(15); /*note - mark_dsw must not be local, caller must be able to test it*/ call mark(event, seconds, 2, mark_dsw); if mark_dsw^=no_error /*cant call syserror or may get in infinite loop*/ then call put_skip_list('error from mark time (MRKT$), dsw = ', mark_dsw); end; cancel_mark_time: procedure(event); dcl event fixed bin(15); call canmt(event, mark_dsw); if mark_dsw^=no_error /*cant call syserror or may get in infinite loop*/ then call put_skip_list('error from cancel mark time (CMKT$), dsw = ', mark_dsw); end; /**************************************************************************************************************/ /* detach the terminal - this appears to be necessary on M-PLUS, which for some inscrutable reason doesn't do break-through writes on system messages such as the abort notification, leading to screwy hang-ups on abort if terminal still attached. note that this is necessary only because we need to do a remove - when we can set auto remove on exit, we wont have to wait on the abort, and so wont care whether the abort message waits for us to exit. */ call detach_ti; if user_exit_status = still_running then do; call mark_time(time_event, 5); /*give user 5 secs to get out*/ if mark_dsw = no_error then call wflor(exit_event, time_event); if user_exit_status = still_running then do; /* abort user task. this code is a bit convoluted because there doesnt seem to be any simple way to tell when the user task is gone - on an abort directive, RSX initiates the abort but does not wait for the abort to complete before returning to caller. You would think that waiting on exit_event after the abort would be the logical solution, but that doesnt work (the REM consistently gets a task active error). So we're left with the following - repeatedly abort and delay a little until we get task not active. Note that this problem exists only because we have to do an explicit remove - when we have automatic remove-on-exit, we can just call abort without caring when it completes. In the mean time, if the remove does fail due to task active, the user will get a task name in use error the next time he uses the debugger, but it will be cleared up the time following that (when the debugger gets the task name in use error on the install, if falls through here and does the remove). */ call cancel_mark_time(time_event); call mark_time(time_event, 7); /*wait up to 7 secs for RSX to complete the abort*/ if mark_dsw^=no_error then call clref(time_event); /*if cant time out, wait indefinitely (RSX should get to it)*/ debug_exit_status = EX_SEV; /*return exit status for abort*/ abort_not_complete = true; do while (abort_not_complete & ^ readef(time_event)); call abort(usertaskrad50, dsw); /*at this point, we always wait a second. if there was no error on the abort, we wait to give up the processor & get out of the way of the abort process before looping back. if there was a task not active error, we must also wait or else the remove will still give a "task active" error, despite the abort having returned a not active!! (this may no longer be necessary now that we are doing a detach)*/ call cancel_mark_time(delay_event); call mark_time(delay_event, 1); if mark_dsw=no_error then call wflor(delay_event); /*now we check the error from the abort...*/ if dsw^=no_error then do; if dsw^=not_active /*task not active "error" is ok - that's what we want*/ then call put_skip_list('error aborting user task, dsw = ', dsw); abort_not_complete = false; end; end /*of abort do while*/; end; end; if (user_exit_status ^= not_installed) & ^ user_was_installed then do; call mcrprv('REM '!!usertaskname, dsw); if dsw^=no_error then call put_skip_list('error removing user task, error code = ', dsw); end; close file(workfile) env(delete); if window_top ^= 0 then call canwindow; /*cancel window if there is one*/ if debug_exit_status ^= EX_SUC then call exstat(debug_exit_status); /*exit with appropriate status*/ end;