Page 1 of 1

Illegal execution with a 'Close' Notifier

Posted: Fri Apr 05, 2019 10:49 am
by Robert
I wish to be informed when a particulat Text Window is closed, and use the following code fragments...

Code: Select all

TYPE
  CloseNotifier  =  POINTER TO RECORD (Sequencers.Notifier)
                      text: TextModels.Model
                    END;
  VAR
    cNotif: CloseNotifier;
    myText: TextModels.Model;

PROCEDURE (c: CloseNotifier) Notify (VAR msg: Sequencers.Message);
  BEGIN
    IF  c.text = myText  THEN  myText  :=  NIL  END
  END Notify;
...
    v  :=  TextViews.dir.New (myText);
    Views.OpenAux (v, 'My document name');
    NEW (cNotif); cNotif.text  :=  myText;
    v.Domain ().GetSequencer ()(Sequencers.Sequencer).InstallNotifier (cNotif)
If/when the Window is closed the variable myText is set to NIL.

This works fine, but the problem is if I unload the Module, then close the Window, I get an "illegal execution (adr = 688E98C9H)" TRAP.
This chain of events only happens during development, so is not much of a problem. However is any "illegal execution" of this type a violation of BlackBox's claim to be a safe programming environment?

Re: Illegal execution with a 'Close' Notifier

Posted: Fri Apr 05, 2019 6:53 pm
by Ivan Denisov
Dear Robert, can you please make some draft with documentation for Sequencers module?
I need to understand it's work better. For example, can it be used to be notified if window becomes "Dirty" the same way as closed?

According your problem. I agree, that this is not OK. I think that you can prevent this by removing the notifier in CLOSE section of your module.

There are also some difficulties, that I am finding annoying. For example, repeated TRAP windows in some cases. They make impossible to save draft of module correctly sometimes.

Re: Illegal execution with a 'Close' Notifier

Posted: Sat Apr 06, 2019 4:30 am
by Ivan Denisov
Why CloseNotifier called twice?

Code: Select all

MODULE DemoSequencers;

IMPORT Log, TextModels, Sequencers, Views, TextViews;

TYPE
	CloseNotifier  =  POINTER TO RECORD (Sequencers.Notifier) END;

	VAR cNotif: CloseNotifier;
	
	PROCEDURE (c: CloseNotifier) Notify (VAR msg: Sequencers.Message);
	BEGIN
		Log.String('view closed'); Log.Ln;
	END Notify;

	PROCEDURE Do*;
	VAR v: TextViews.View;
	BEGIN
		v  :=  TextViews.dir.New(TextModels.dir.New());
		Views.OpenAux (v, 'My document name');
		NEW (cNotif);
		v.Domain().GetSequencer()(Sequencers.Sequencer).InstallNotifier(cNotif)
	END Do;

CLOSE
	
END DemoSequencers.

^Q DemoSequencers.Do

Re: Illegal execution with a 'Close' Notifier

Posted: Sat Apr 06, 2019 5:23 am
by cfbsoftware
The call sequence for the first call to CloseNotifier is:

...
HostCmds.Close
HostCmds.CloseWindow
Sequencers.Sequencer.Notify
DemoSequencers.CloseNotifier.Notify

The call sequence for the second call to CloseNotifier is:

...
HostCmds.Close
HostCmds.CloseWindow
HostWindows.Directory.Close
HostWindows.Window.Close
Windows.Window.Close
Sequencers.Sequencer.Notify
DemoSequencers.CloseNotifier.Notify

Does that help answer your question?

Re: Illegal execution with a 'Close' Notifier

Posted: Sat Apr 06, 2019 5:57 am
by Ivan Denisov
Thank you, Chris. I see, that Notify called in two places.

Also I mentioned, that there is no way to remove notifiers... I think, that in case of problem, which Robert had mention, this is no good. Maybe we should add procedure UninstallNorifier?

Re: Illegal execution with a 'Close' Notifier

Posted: Sat Apr 06, 2019 6:36 am
by Ivan Denisov
It works. I have checked it.

Code: Select all

...
	PROCEDURE (s: Sequencer) UnistallNotifier* (n: Notifier), NEW;
	VAR tmp: Notifier;
	BEGIN
		IF s.notifiers = n THEN
			s.notifiers := s.notifiers.next
		ELSE
			tmp := s.notifiers;
			WHILE (tmp.next # NIL) & (tmp.next # n) DO
				tmp := tmp.next
			END;
			IF tmp.next # NIL THEN
				tmp.next := tmp.next.next
			END
		END
	END UnistallNotifier;


END Sequencers.
That is safe module. It can be unloaded without such troubles.

Code: Select all

MODULE DemoSequencers;

IMPORT Log, TextModels, Sequencers, Views, TextViews;

TYPE
	CloseNotifier  =  POINTER TO RECORD (Sequencers.Notifier) END;

	VAR
		cNotif: CloseNotifier;
		v: TextViews.View;
	
	PROCEDURE (c: CloseNotifier) Notify (VAR msg: Sequencers.Message);
	BEGIN
		Log.String('view closed'); Log.Ln;
	END Notify;

	PROCEDURE Do*;
	BEGIN
		v  :=  TextViews.dir.New(TextModels.dir.New());
		Views.OpenView(v);
		NEW (cNotif);
		v.Domain().GetSequencer()(Sequencers.Sequencer).InstallNotifier(cNotif)
	END Do;

	PROCEDURE Unload*;
	BEGIN
		IF v # NIL THEN
			v.Domain().GetSequencer()(Sequencers.Sequencer).UnistallNotifier(cNotif)
		END
	END Unload;

CLOSE
	Unload
END DemoSequencers.

Re: Illegal execution with a 'Close' Notifier

Posted: Sat Apr 06, 2019 10:14 am
by Robert
Ivan Denisov wrote:According your problem. I agree, that this is not OK. I think that you can prevent this by removing the notifier in CLOSE section of your module.
I decided that this was a real problem for me; I couldn't close the Window without closing BlackBox. To avoid it I now close the Window in the CLOSE section of my module. I already had a routine to do that (in LibMisc):

Code: Select all

PROCEDURE  CloseModelWindows* (model : Models.Model; askIfDirty : BOOLEAN) : INTEGER;
  VAR
    w, w2     :  Windows.Window;
    wTitle    :  Views.Title;
    res, cnt  :  INTEGER;
    ask       :  BOOLEAN;
  BEGIN
    cnt  :=  0;
    IF  model  #  NIL  THEN
      w  :=  Windows.dir.First (); ask  :=  TRUE;
      WHILE  w  #  NIL  DO
        w2  :=  w; w  :=  Windows.dir.Next (w);
        IF  w2.doc.ThisView ().ThisModel ()  =  model  THEN
          IF  w2.seq.Dirty ()  THEN
            IF  askIfDirty  THEN
              IF  ask  THEN
                w2.GetTitle (wTitle); ask  :=  FALSE;
                Dialog.GetOK ('Close Dirty model in window ^0 ?', wTitle, '', '',
                              {Dialog.yes, Dialog.no, Dialog.cancel}, res)
              END
            ELSE
              res  :=  Dialog.yes
            END;
            IF     res  =  Dialog.yes     THEN  w2.Close; INC (cnt)
            ELSIF  res  =  Dialog.cancel  THEN  w  :=  NIL  END
          ELSE
            w2.Close
          END
        END
      END
    END;
    RETURN  cnt
  END  CloseModelWindows
I agree that a new procedure UninstallNotifier would be a useful addition.

But my point is not about how to deliberately avoid this trap, but if avoiding it should be automatic (somehow) so that it is impossible to get this Illegal execution.

There is some documentation about Notifiers in https://wiki.blackboxframework.org/inde ... Sequencers.

Re: Illegal execution with a 'Close' Notifier

Posted: Sat Apr 06, 2019 10:37 am
by Robert
Ivan Denisov wrote:Dear Robert, can you please make some draft with documentation for Sequencers module?
I need to understand it's work better. For example, can it be used to be notified if window becomes "Dirty" the same way as closed?
I don't know how to be notified when a window becomes Dirty, but agree that it could be a useful feature.