bugGNU Octave - Bugs: bug #54231, GUI attempts to open file for...

 
 

bug #54231: GUI attempts to open file for function declared at top-level

Submitter:  Doug Stewart <dastew>
Submitted:  Mon 02 Jul 2018 02:46:05 PM UTC
   
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  None
Status:  Fixed Assigned to:  None
Originator Name:  Doug Stewart Open/Closed:  * Closed
Release:  * 4.4.0 Operating System:  * GNU/Linux
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Sat 14 Jul 2018 04:35:22 AM UTC, comment #20: 

Closing report as the original issue has been fixed.

Rik <rik5>
Group administrator
Mon 09 Jul 2018 11:39:49 PM UTC, comment #19: 

If I find time, I may look at this later.  However, I can see what the issue is.  The ggg() is merely a base-class octave_function object, and for the virtual function fcn_file_name is returned an empty string "":


@linux ~/octave/octave/octave $ grep fcn_file_name */*/*.h -slibinterp/corefcn/call-stack.h:      std::string fcn_file_name (void) const;
libinterp/octave-value/ov-dld-fcn.h:  std::string fcn_file_name (void) const;
libinterp/octave-value/ov-fcn.h:  virtual std::string fcn_file_name (void) const { return ""; }
libinterp/octave-value/ov-mex-fcn.h:  std::string fcn_file_name (void) const;
libinterp/octave-value/ov-usr-fcn.h:  void stash_fcn_file_name (const std::string& nm) { file_name = nm; }
libinterp/octave-value/ov-usr-fcn.h:  std::string fcn_file_name (void) const { return file_name; }
libinterp/parse-tree/lex.h:        m_fcn_file_name (),
libinterp/parse-tree/lex.h:    std::string m_fcn_file_name;


In the dbwhere routine, an empty function doesn't display the file info:


DEFMETHOD (dbwhere, interp, , ,
[snip]
{
  octave::tree_evaluator& tw = interp.get_evaluator ();

  octave_user_code *dbg_fcn = tw.get_user_code ();

  if (! dbg_fcn)
    {
      octave_stdout << "stopped at top level" << std::endl;
      return ovl ();
    }

  octave_stdout << "stopped in " << dbg_fcn->name () << " at ";

  octave::call_stack& cs = interp.get_call_stack ();

  int l = cs.debug_user_code_line ();

  if (l > 0)
    {
      octave_stdout << "line " << l;

std::cerr << "\nGetting the FILENAME!\n";
      std::string file_name = dbg_fcn->fcn_file_name ();

      if (! file_name.empty ())
        {
          octave_stdout << " [" << file_name << ']' << std::endl;

          std::string line = dbg_fcn->get_code_line (l);

          if (! line.empty ())
            octave_stdout << l << ": " << line << std::endl;
        }
      else
        octave_stdout << std::endl;
    }
[snip]


It seems to me that the ggg() routine should be elevated to an ov-usr-fcn, ov-mex-fcn or ov-dld-fcn, but I can't find where in the parse code that determination is made.  (I searched for things like "new octave_function", etc.)

Dan Sebald <sebald>
Mon 09 Jul 2018 10:50:35 PM UTC, comment #18: 

@Rik: Ah, the myfunc() example is a case where there is no file, so the line number is a reference to the offset into the function definition itself.  In the ggg() example, I'm remembering that the line number was 4 which is the number of the file line.  The number of the ggg() start offset would be 2.  So ggg() only has "scope" during the execution stage, for otherwise when not in scope it could be ggg() originating from any number of script files. 

If not in debug mode, placing a breakpoint in the middle of ggg() in yourtest.m results in


>> dbstatus
breakpoint in yourtest at line 4


So that ggg() function is not resolved until the execution stage.  But when it is resolved in this case, the information we are told is somewhat incorrect.  Either it should be saying


debug> dbwhere
stopped in yourtest at line 4 [/home/sebald/matlab/bug/54231/yourtest.m]


or


debug> dbwhere
stopped in ggg at line 2


Ideally for this case, it would seem that


debug> dbwhere
stopped in ggg [/home/sebald/matlab/bug/54231/yourtest.m] at line 4


where the line 4 is referenced to the yourtest.m file is the most useful.  That way the editor can figure out where to put the yellow arrow easily.  If the routine were to report "ggg at line 2", the editor would have to go through the code and figure out at which line ggg starts.  Or perhaps both pieces of information should be displayed, e.g.,


debug> dbwhere
stopped in ggg at line 2 [/home/sebald/matlab/bug/54231/yourtest.m at line 4]


Dan Sebald <sebald>
Mon 09 Jul 2018 09:57:06 PM UTC, comment #17: 

@Dan: Just for clarity, I have uploaded yourtest.m which is a copy of the OP's code.

The reason that dbwhere is faliing in the CLI is related to how functions are parsed in scripts.  When you execute a script that defines functions those functions are entered in to the symbol table as command-line functions.

Here is an example in action.


octave:1> diary on
octave:2> which ggg
octave:3> source yourtest.m
a =  1
x =  3
ans =  3
octave:4> which ggg
'ggg' is a command-line function
octave:5> dbstop ggg
ans =  4
octave:6> ggg (8)
error: called from
    ggg at line 4 column 4
error: ggg: no such file, ''
octave:6> diary off


The issue is that the command-line function has the file name '' (i.e., blank) associated with it and when Octave goes to print the necessary debug information it finds no file and emits an error.

But, notice that this isn't the case with a true command-line function.


octave:1> diary on
octave:2> function y = myfunc (x)
> y = 2 * x;
> endfunction
octave:3> dbstop myfunc
ans =  2
octave:4> myfunc (8)
debug> dbwhere
stopped in myfunc at line 2
debug> dbquit


So, it can be made to work.  Octave is probably setting some of the symbol table meta-information to specific values when it is a true command-line function.




(file #44529)

Rik <rik5>
Group administrator
Mon 09 Jul 2018 09:15:40 PM UTC, comment #16: 

I've tested.  That looks appropriate.

As for getting the file information:


debug> dbwhere
stopped in yourtest at line 7 [/home/sebald/matlab/bug/54231/yourtest.m]
7: ggg(8)
debug>
[I clicked the Step-In GUI button]
debug> dbwhere
stopped in ggg at line 4


JWE would know what the issue is.  It seems like the information should be readily available, given that the line number is known.

Dan Sebald <sebald>
Mon 09 Jul 2018 08:32:04 PM UTC, comment #15: 

Changeset http://hg.savannah.gnu.org/hgweb/octave/rev/eee01a6e197f allows to set a breakpoint in an unnamed editor file instead ignoring the click into the margin (as solution for comment #4 as discussed in comment #10 and comment #11).

Torsten Lilge <ttl>
Group Member
Sun 08 Jul 2018 07:38:14 AM UTC, comment #14: 

@Rik: There is no specific reason, I just copied the code sequence from another source file and will simplify both ocurrances.

@Dan: The difference is that the "step in" command is called by the GUI with suppressing printing the location in the command line. You can change this in the preferences dialog (tab "Command", option "Print debug location ..."). Enabling this also lead to the error message. Please note, that this error is not the one of the OP. This error is not related to the GUI and also occurs in the cli-version.

The information on the line number 4 and the function 'ggg' is passed to the GUI by octave_link::enter_debugger_event (). However, this is not sufficent for the GUI to open the related editor file which is not 'ggg.m'. Is there a way to also provide the real file name here?

Torsten Lilge <ttl>
Group Member
Sun 08 Jul 2018 04:51:12 AM UTC, comment #13: 

@Torsten: In the patch, is there a specific reason to convert to Qstring from std::string in order to compare it to a constant?  The C++ std::string class implements the '==' operator.


+    QString type = QString::fromStdString (
+                    map.contents ("type").data ()[0].string_value ());
+    if (type == QString ("command-line function"))


Seems like you could just keep type as std::string.


+    std::string type = map.contents ("type").data ()[0].string_value ());
+    if (type == "command-line function")




Rik <rik5>
Group administrator
Sat 07 Jul 2018 10:39:40 PM UTC, comment #12: 

OP: OK, this is strange.  I used the GUI debugger icon to step through, and it worked.  But the behavior is as you describe when I step via the command line (my "yourtest.m" file contains the original example):


>> yourtest
a =  1
stopped in /home/sebald/matlab/bug/54231/yourtest.m at line 7
7: ggg(8)
debug> dbwhere
stopped in yourtest at line 7 [/home/sebald/matlab/bug/54231/yourtest.m]
7: ggg(8)
debug> dbstep in
error: ggg: no such file, ''
error: called from
    ggg at line 4 column 4
    yourtest at line 7 column 1


The above was with the command line, i.e., "dbstep in".  However, here is if I use the Step-In icon to step through the file:


>> yourtest
a =  1
stopped in /home/sebald/matlab/bug/54231/yourtest.m at line 7
7: ggg(8)
debug>
debug> dbwhere
stopped in ggg at line 4
debug>


Notice how I was able to retrieve the needed information about where the yellow arrow-cursor via the dbwhere function; line 4 is the "x=3" line inside of ggg() function.  I imagine the GUI is using the special debug functions that the command line function isn't using.  Many moons ago I proposed a simple background queue for which the GUI could call these informational functions and get an octave-variable type in return.

Dan Sebald <sebald>
Sat 07 Jul 2018 06:23:12 PM UTC, comment #11: 

Dan, thanks for testing.

OP:

The message ("ggg unknwon, should it be created?") appears when the yellow "program counter" (PC) should be drawn. This is thescenario described in the OP: Setting the breakpoint on "ggg(8)" and when program is interrupted there, then "step into". Since the file "ggg" is not known, there is no way to open the file at the desired line.

A solution might be to get these informations from the working thread when entering debugging or to completely parse the file again in the gui thread.

Comment #4:

I see your point and will change the behavior accordingly.

Torsten Lilge <ttl>
Group Member
Sat 07 Jul 2018 06:08:59 PM UTC, comment #10: 

I'm testing the changes here.

Original Post) The error message no longer appears and Step-Into proceeds with the program, printing out


>> yourtest
a =  1
x =  3


However, there is no yellow program line arrow indicating the current line inside the ggg() inline function.  If I'm understanding correctly, the yellow arrow should go from the line containging ggg(8), (click Step icon) to inside the ggg(t) inline routine, (click Step icon) to just after the ggg(8) routine (after printing "x = 3").  In other words, right now it's as if the current executing line disappears when it should still be visible within this file.

Comment #4) The crash is gone, the unusual message for empty file has gone.  Those issues have been fixed, thanks.  However, I still see one small detail that isn't quite right.  There may be two nuances of the same issue: the breakpoint attempted at the empty line is remembered when later a new breakpoint is set after some valid code has been entered and the file saved (this is difficult to repeat precisely) and one can set the breakpoint at the blank line in an empty file.  To illustrate:

1) Open a new "unnamed" file.
2) Save the file as "testing123.m"
3) Click on blank line "1".

At that point a breakpoint icon appears.  Also, there is a registered breakpoint:


>> dbstatus
breakpoint in testing123 at line 1


Furthermore, the registered breakpoint behaves like the conventional breakpoint.  That is, if one runs "testing123" at the command line, the program will break at line 1 of the file and the editor highlights said line.

Now, whether that breakpoint should be allowed is one question, but I suppose the argument can be made that testing123.m is like a function with an empty first line--don't know.

However, Torsten I think that we'll have to make the clicking on a blank line in a fresh file be consistent with the unsaved file warning message, i.e., "Cannot add breakpoint to modified file.
Save and add breakpoint, or cancel?" simply because having a breakpoint in an empty file is currently valid.  I believe this is how the "remembered" breakpoint comes about too--create a new unnamed file, attempt a breakpoint on the empty line and internally a breakpoint is actually set but the editor isn't showing that because of the logic in the recent changeset...until later when the user creates some valid text and adds another breakpoint.  Then the editor believes it can set breakpoints, so refreshes and the two breakpoints appear where there was none prior to the action.

Dan Sebald <sebald>
Sat 07 Jul 2018 02:36:23 PM UTC, comment #9: 

And finally, cset
http://hg.savannah.gnu.org/hgweb/octave/rev/2d588bad7d9e
prevents setting a breakpoint in an unmodified and still unnamed editor tab.

Torsten Lilge <ttl>
Group Member
Sat 07 Jul 2018 11:51:46 AM UTC, comment #8: 

I have pushed cset
http://hg.savannah.gnu.org/hgweb/octave/rev/bb779fc2d0db
which fixes issues from the original post and comment #3.

Torsten Lilge <ttl>
Group Member
Mon 02 Jul 2018 08:36:49 PM UTC, comment #7: 

Changeset http://hg.savannah.gnu.org/hgweb/octave/rev/15460ae5462d fixes the crash from comment #4 case 1.

Still open:

  • Prevent any action when trying to set a breakpoint in an "unnamed" and unmodified editor tab


  • The issue from the OP


Torsten Lilge <ttl>
Group Member
Mon 02 Jul 2018 07:04:22 PM UTC, comment #6: 

The crash always happens when closing the dialog box with the 'X'.

Torsten Lilge <ttl>
Group Member
Mon 02 Jul 2018 06:55:26 PM UTC, comment #5: 

@Dan (comment #4): I think the issue is that in your first case, the not modified editor tab is handled like an ordinary opened file. In a not modified "unnamed" tab (which must be empty) setting a breakpoint should not result in any action at all. I am going to fix this.

The second case is handled correctly, since you are trying to add a breakpoint to a modified tab, regardless its "unnamed" state.

Torsten Lilge <ttl>
Group Member
Mon 02 Jul 2018 05:47:51 PM UTC, comment #4: 

I saw something probably related the other day, but disregarded it because it didn't seem too significant.  But now that I try this again, the bug seems worse than I remember (but the crash is intermittent).  This could be a GUI issue too, and not necessarily something fundamental in the way breakpoints are processed.  It may be worth addressing the following at the same time:

1) Launch Octave with GUI and open the Editor, either floating or not floating.

2) Create a new file by selecting the New Script icon (the left-most icon in the toolbar).

3) Without adding any text to the file titled "<unnamed>", mouse click in the empty left column where breakpoint icons typically appear.

The result is a dialog box that appears titled "Change Directory or Add Directory to Load Path" with a message "The file does not exist in the load path.  To run or debug the function you are editing, you must either change to the directory or add that directory to the load path."  I'm attaching a screen shot of the dialog box.

My way of thinking is that I've clicked on a line where for certain there cannot be a breakpoint.  Perhaps it isn't easy to determine if there can or can't be a breakpoint because the design may intentionally be to select the nearest breakpoint.

Anyway, if I then select the X to cancel the dialog box, Octave GUI crashes with "octave exited with signal 11".

If I repeat steps 1 and 2, but this time place a simple for-loop in the new file without saving then again click in the breakpoint column, the error message is slightly different.  It is titled "Octave Editor" and reads "Cannot add breakpoint to modified file.  Save and add breakpoint, or cancel?"  This time canceling does not crash Octave GUI.

Again, my report seems like it could be more GUI related, but the inconsistency of the error message seems strange and the "The file does not exist in load path" message is reminiscent of the original post.


Dan Sebald <sebald>
Mon 02 Jul 2018 04:58:56 PM UTC, comment #3: 

I'm adding jwe to the CC list.

The issue is when the GUI needs access to a function, say to follow the code execution line-by-line when operating in the debugger, and that function is not associated with any file, for example it was declared on the command line, then the editor can't find said function and throws up a warning dialog window.

Steps to reproduce:

1) Use the built-in editor of the GUI (Preferences)
2) Launch the GUI (run-octave --gui)
3) Declare a function at the command line


function r = myfunc ()
  r = pi
end


4) Set a breakpoint in the function


dbstop myfunc


5) Execute the function


myfunc


This throws up the warning dialog, "File myfunc does not exist. Do you want to create it?"


Rik <rik5>
Group administrator
Mon 02 Jul 2018 03:47:40 PM UTC, comment #2: 

The code shown was in a file. I used the editor gui to place the break points. and I used the editor buttons to step through.

Doug Stewart <dastew>
Mon 02 Jul 2018 03:27:16 PM UTC, comment #1: 

Where is the code that you referenced?  Is it in a file or was it typed at the command line?

Does it work if you use the Command Window and dbstop, rather than the GUI?

Rik <rik5>
Group administrator
Mon 02 Jul 2018 02:46:05 PM UTC, original submission:  

While I was trying to debug some GSoC work I ran up against this problem.

If you run the shown code it works fine.
If you put a breake point on the ggg(8) line,
and then use the stepinto Icon of the editor window
Octave stops and asks:

file
ggg
does not exist. Do you want to create it?


Somehow in debug mode the inline function is not known!




a=1

function x=ggg(t)
  x=3
endfunction

ggg(8)



Doug Stewart <dastew>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by ttl (Posted a comment)
  • -email is unavailable- added by sebald (Updated the item)
  • -email is unavailable- added by rik5
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by dastew (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 11 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2018-07-14 rik5 StatusReady For Test Fixed
        Open/ClosedOpen Closed
    2018-07-09 rik5 Attached File- Added yourtest.m, #44529
    2018-07-07 ttl StatusConfirmed Ready For Test
    2018-07-02 sebald Attached File- Added dialog_when_pressing_breakpoint_area_of_empty_new_file_Screenshot_from_2018-07-02_12-14-30.png, #44490
        Attached File- Added dialog_when_pressing_breakpoint_area_of_forloop_unsaved_new_file_Screenshot_from_2018-07-02_12-38-25.png, #44491
    2018-07-02 rik5 StatusNeed Info Confirmed
        SummaryIn debug mode an inline function is not known. GUI attempts to open file for function declared at top-level
        Carbon-Copy- Added jwe
    2018-07-02 rik5 CategoryNone Interpreter
        StatusNone Need Info

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code