patchGNU Octave - Patches: patch #8016, GUI <--> interpreter...

 
 

patch #8016: GUI <--> interpreter threading issues - prototype octave_value_list transfer

Submitter:  Dan Sebald <sebald>
Submitted:  Sat 13 Apr 2013 09:57:00 AM UTC
   
 
Category:  Core : new feature Priority:  3 - Low
Status:  Wont Do Privacy:  Public
Assigned to:  None Open/Closed:  Closed
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Mon 20 Jan 2020 04:35:51 AM UTC, comment #14: 

The situation from 2013, when this patch was written, seems to have entirely changed to the better.

I think no one can really benefit from working on this patch in 2020.  As jwe already said in comment #13, if there are problems with threading:

> please report specific bugs.


Closing this item.

Kai Torben Ohlhus <siko1056>
Group Member
Sun 19 Jan 2020 10:54:34 PM UTC, comment #13: 

Using reference counting for objects that are used in multiple threads is no problem if you ensure that any operations on the reference count or the data that they protect is handled in a thread-safe way.  I believe that we are passing objects and invoking interpreter functions from the GUI (or GUI functions from the interpreter) in thread-safe ways.  If not, then please report specific bugs.

John W. Eaton <jwe>
Group administrator
Sun 19 Jan 2020 10:09:41 AM UTC, comment #12: 

At least the issue with commands sent from the GUI to the interpreter where a result is sent back to the GUI was solved with changeset http://hg.savannah.gnu.org/hgweb/octave/rev/a7511a1489b8 (bug #47585).

The approach was later updated by jwe using lambda functions.

Torsten Lilge <ttl>
Group Member
Sun 19 Jan 2020 12:29:11 AM UTC, comment #11: 

Dan, thanks for the feedback and enlightening me.  The mentioned post by jwe is this one:

https://lists.gnu.org/archive/html/octave-maintainers/2019-09/msg00071.html

I rename this item so others get the idea easier.

Kai Torben Ohlhus <siko1056>
Group Member
Sat 18 Jan 2020 07:50:44 PM UTC, comment #10: 

Maybe.  There were one or two fairly recent discussions on the list about transferring data back and forth between the GUI and octave core (what's called a worker thread).

rethinking interpreter <-> gui interaction
[thought there was one in which was examining reference counting]

JWE was revisiting the issue within the past six months.  I don't know where it stands.  Any patches attached here have probably long been out of date, but as far as the issue, I think it still exists.

The problem stems from the fact reference counting across the thread to the  GUI is dangerous (we all had enough experience with reference counting to know such a scheme would eventually crash) and to make the transfer of data to the GUI more generic rather than having specific functions to get this data or that data.  The scheme here moves the data without affecting the atomic reference count.  (octave_value_list is the most generic form of data in Octave, it's what all functions return internally.  Thus if the GUI requests a command, it can get an octave_value_list containing all the results.)

Dan Sebald <sebald>
Sat 18 Jan 2020 12:47:17 PM UTC, comment #9: 

Review for Octave 6.

@Dan: Is this patch still relevant? I do not understand it's purpose.

Kai Torben Ohlhus <siko1056>
Group Member
Sat 20 Sep 2014 09:27:15 AM UTC, comment #8: 

I forgot to add the disconnecting step for which I left a reminder below.

This new patch adds the disconnect when the add_all_breakpoints() slot is no longer needed.  I verified proper operation with fprintf() calls.  To make it work properly at startup, I had to move the file_editor restore session code to its own function and call that after the octave_qt_link and editor_window are both constructed and connected.  Otherwise, the file_editor_tab was queuing commands when there was no link to Octave core yet available.


(file #32140)

Dan Sebald <sebald>
Fri 19 Sep 2014 10:15:59 PM UTC, comment #7: 

Here's an update to the changeset/patch.  It's fundamentally the same, but the changeset is quite different from the past versions because I moved the existing "queue_command"-related code for the terminal from main-window.cc to octave-qt-link.cc.


(file #32139)

Dan Sebald <sebald>
Fri 26 Apr 2013 06:02:49 PM UTC, comment #6: 

Noting that I tested a similar trans-thread communication as part of the dialogs changeset here:

https://savannah.gnu.org/patch/index.php?7990

Fri 26 Apr 2013 05:57:45 PM GMT, comment #25:

I found that the communication was robust with or without checking on the GUI side that the mutex can be locked before awakening the worker thread.

Dan Sebald <sebald>
Thu 18 Apr 2013 08:23:29 AM UTC, comment #5: 

Yes, discussion on maintainers list is fine.

I remember something I thought about earlier in the day so I'm going to write a note here to not forget.  Once a file is opened there really isn't a need for the connection between the background command result signal and the add_all_breakpoints() slot.  I just tested that


  disconnect (sender (),
              0,
              this,
              SLOT (add_all_breakpoints (const QObject *,
                                         const QString&,
                                         const int,
                                         const octave_value_list&)));


at the end of add_all_breakpoints will break the connection.  I think it's better left as is though for the moment because it might help uncover some other things with the debugger when that comes up.

Dan Sebald <sebald>
Thu 18 Apr 2013 07:44:31 AM UTC, comment #4: 

If you want to discuss this, how about using the maintainers list?

John W. Eaton <jwe>
Group administrator
Thu 18 Apr 2013 07:39:53 AM UTC, comment #3: 

Here's a changeset with a little more clean up and the callback code removed.  Same code as previous changeset, but the fprintf statements have been removed.

(file #27903)

Dan Sebald <sebald>
Thu 18 Apr 2013 05:45:16 AM UTC, comment #2: 

Attached is a changeset that replaces the callback functions with a background command queue.  (Actually, this is very similar in behavior, using the do_process_events() poll loop as a starting point.)  The feature it adds is passing command results back to the GUI in the background.  It uses QMutex and QWaitCondition to make sure the Octave worker thread is in a wait state before handling data on the GUI side of the thread divide.  octave_value_list does no copy/delete in the signal/slot queuing mechanism across threads.

For this version of the changeset I've left in a number of fprintf()s to give a person an idea of what is happening, and to coincide with the results to follow.  I've also used USE_CALLBACKS to ifdef out code rather than removing everything.  That will make the changeset diff file a little smaller and easier to follow.  I will create a new changeset with callbacks removed in a hour or two.

Here are comments from working with this:

1) Consider renaming libinterp/interp-core/oct-obj.h to libinterp/interp-core/ov-list.h or something similar.  It took a long time for me to find where octave_value_list is declared.

2) There is already something like the Octave background command.  It is QTerminal::relay_command (command) which sends a command to the input stream of Octave core and is used in a couple places for changing a directory and whatnot.  However, that does not allow returning data and always puts some text on the terminal output and command history list.  The background command queue is kind of nice in the sense it is low priority GUI events that happen between Octave worker thread's bigger tasks when idle at the command line.

3) Right now, there is a bit of mixing and matching with the octave_link.  In some cases there are calls to static functions.  In some cases a pointer to an instance of the object is used.  Perhaps just one method is preferred down the road.

4) I put some fprintf commands at key locations (not include in this patch...to verbose and slow):

  • octave_value copy constructor
  • wherever there is a octave_value refcount decrement
  • right before emitting signal across threads
  • right after emitting signal across threads

First, there are an absolute ton of copies and destructs of octave_values for any sort of activity, even trivial things like "return" at the command line.  If atomic references means more sophisticated copy, slowness will be an issue.

Second, here is a sample in which a breakpoint is set so that Octave core does a "dbstop" via eval_string() (I typed AAAA so that I new where the response began for the command):


octave:1> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYour wish is my command:  dbstop ("testfun", 4);
Made an octave_value copy.
Destructed an octave_value.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Made an octave_value copy.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Here's right before transmitting signal.
Here's right after transmitting signal.
GUI?  Here's the result for:  dbstop ("testfun", 4);
This isn't for me.
OK, All done.
Destructed an octave_value.


Note all the activity going on in the core.  And note that there appears to be no octave_value copy happening between before and after emitting (i.e., queueing) the signal transferring data across the thread.  (That's the 5th and 6th last line above.)  I take it that means that using octave_value_list is better than using octave_value.

To verify this, I changed the emitted signal so that it has an unused octave_value as one of its arguments like this:


octave_value junk;
fprintf (stderr, "Here's right before transmitting signal.\n");
      emit transmit_octave_command_result (ci.senderid, ci.command,
                                           command_status, retval, junk);
fprintf (stderr, "Here's right after transmitting signal.\n");


and for a similar "dbstop" command get the following output:


octave:1> BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBYour wish is my command:  dbstop ("testfun", 6);
Made an octave_value copy.
Destructed an octave_value.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Made an octave_value copy.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Made an octave_value copy.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Destructed an octave_value.
Removed an octave_value via operator.
Destructed an octave_value.
Destructed an octave_value.
Here's right before transmitting signal.
Made an octave_value copy.               <<<<<<<<<<<<  NOTICE (NOTE ADDED MANUALLY)
Here's right after transmitting signal.
Destructed an octave_value.
GUI?  Here's the result for:  dbstop ("testfun", 6);
This isn't for me.
OK, All done.
Destructed an octave_value.              <<<<<<<<<<<<  NOTICE (NOTE ADDED MANUALLY)
Destructed an octave_value.


Notice that there is an octave-value-copy associated with the emitted (queued) signal and an extra destructor call associated with everything finished when including an octave_value in the list of arguments.  The above is the dangerous scenario because rep->count can be modified in an intermixed way between threads.  Hence, octave_value_list is the preferred data format.

Lastly, here's the situation when a routine in the GUI thread actually uses the data from the octave_value_list signaled from the Octave worker thread.  (I had to add more specific fprintf count++ and --count to tally things.)  This is the dbstatus command when attempting to restore breakpoints:


octave:1> CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCYour wish is my command:  dbstatus ();
Created octave_value:  count++
[SNIP]
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Here's right before transmitting signal.
Here's right after transmitting signal.
GUI?  Here's the result for:  dbstatus ();
Created octave_value:  count++           <<<<<<<<< NOTICE START
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Created octave_value:  count++
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Created octave_value:  count++
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Created octave_value:  count++
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Created octave_value:  count++
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Created octave_value:  count++
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Created octave_value:  count++
Removed an octave_value via operator.  --count
Created an octave_value via operator:  count++
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Destructed an octave_value:  --count
Destructed an octave_value:  --count     <<<<<<<<<<< NOTICE END
OK, All done.
Now waking worker thread.
Destructed an octave_value:  --count


Notice all that new activity due to the manipulations of octave_value instances in the GUI thread with the command results.  I count 28 --count but only 20 count++.  Maybe I missed some, but the point is that the GUI thread can work on all that data because the Octave worker thread is asleep.  If things are programmed properly, the rep-count changes should be a zero sum and things properly cleaned up by time the GUI is done with computations.

6) With this setup it doesn't seem like atomic reference counting is necessary.  The


// FIXME -- we should not be including config.h in header files.
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif


is getting a little cumbersome though.  Perhaps there is a better way to configure reference counting than having to include <config.h> in derivative header files.

6) I'm not completely happy with the setup for file_editor and file_editor_tab pointers and container classes.  The signal-to-signal connections lose the original sender of the signal.  (Could easily add that to list, but prefer to hold off if it isn't necessary.)  Things are OK now, maybe global _octave_link is better, but not sure.  The critical issue is that right now a file_editor_tab is created, then a ->load_file() is attempted and if that passes then connections are made.  However, it is the load process where an inquiry for dbstatus() should be done, but that requires a connection which isn't yet set.  I just didn't want to mess with that right now and cause problems that are sort of tangent to the code here.  The octave_qt_link is a proper and good mechanism, it's just that this needs cleanup for better sequence of construction--consequence of not being modular and object oriented enough at beginning...which is OK.

7) dbstatus() is the only routine right now using the data coming from the background queue.  The ones that don't need data really don't need the sleep mechanism, but I think it is better to always use that, just for consistency.

8) I think with the setup of having two core slots on both sides of the thread for the outer level GUI objects to attached to is pretty safe.  If folks aren't comfortable with the computations going on in the GUI thread, it wouldn't be too difficult to interpret the commands in the background command queue (e.g., "dbstatus") and then emit signals accordingly.  However, I sort of like things the way they are.  It requires some knowledge on part of the programmer, but it stops the growing list of callbacks that aren't as rigorously defined as the core data objects are.  It also makes for adding new features and behavior rather easy by just compiling GUI code and not having to compile core code.  That is, this is for that class of GUI-initiated, non-workspace modifying events.  (Command line generated is a different issue for a different time.)


(file #27902)

Dan Sebald <sebald>
Mon 15 Apr 2013 03:13:02 AM UTC, comment #1: 

Will try something like this at a later time:

octave_value_list result = eval_string(...,nout)
if (OK)
  for i=0; i< nout; i++
  {
    copy_count(i) = result(i).rep.count;
    result(i).rep.count = -1;
  }
  emit command_result (result)

  put_thread_to_sleep()

  Restore the count
  for i=0; i< nout; i++
  {
    result(i).rep.count = copy_count(i);
  }

None of the copy/deletes going on in the signal/slot mechanism will have any effect on the rep-count.  In the GUI thread would be:

octave-link::handle_command_result (QObject *ID, octave_value_list& result)
{
  // Transmit result to other objects in GUI.
  emit have_command_result (ID, result);

  // No longer need this data
  wake_up_the_worker_thread()
}

Dan Sebald <sebald>
Sat 13 Apr 2013 09:57:00 AM UTC, original submission:  

This a prototype of prototype quality bits and pieces to transfer commands and octave_value_list data across threads.  I used the qtdialogs code as a starting point, so it really isn't too much actual code.  I put PROTOTYPE CONCEPT in spots to identify the needed parts.

The steps to follow are:

1) Enter some type of matrix value at the command line like x = [1:10]'*[1:10]

2) Click on the little red button near the directory file menu.

3) Enter the name of the variable created in the input dialog.  (Pressing OK will queue up two commands, the size of the matrix and the matrix).

4) Enter "qterrordlg ('hello');" at the command line.  (This is supposed to simulate Octave core eventually getting around to processing the commands that have been queued.)

Dan Sebald <sebald>

 

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

Attach Files:
   
   
Comment:
   

Attached Files
file #32140:  octave-background_command-2014sep20.patch added by sebald (46KiB - application/octet-stream)
file #32139:  octave-background_command-2014sep19.patch added by sebald (43KiB - application/octet-stream)
file #27903:  octave-background_command-2013apr18_v2.patch added by sebald (36KiB - application/octet-stream)
file #27902:  octave-background_command-2013apr18_v1.patch added by sebald (33KiB - application/octet-stream)
file #27858:  octave-ovlist_prototype-2013apr13.patch added by sebald (29KiB - application/octet-stream)

 

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 siko1056 (Posted a comment)
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by sebald (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 logged-in users can vote.

     

    Follow 11 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-01-20 siko1056 StatusPostponed Wont Do
        Open/ClosedOpen Closed
    2020-01-19 siko1056 SummaryPrototype octave_value_list transfer GUI <--> interpreter threading issues - prototype octave_value_list transfer
    2020-01-18 siko1056 CategoryNone Core : new feature
        Priority5 - Normal 3 - Low
        StatusNone Postponed
    2014-09-20 sebald Attached File- Added octave-background_command-2014sep20.patch, #32140
    2014-09-19 sebald Attached File- Added octave-background_command-2014sep19.patch, #32139
    2013-04-18 sebald Attached File- Added octave-background_command-2013apr18_v2.patch, #27903
    2013-04-18 sebald Attached File- Added octave-background_command-2013apr18_v1.patch, #27902
    2013-04-13 sebald Attached File- Added octave-ovlist_prototype-2013apr13.patch, #27858

    Back to the top

    Powered by Savane 3.13-758e.
    Corresponding source code