changeset 29258:28913793f678

prefer unwind_action over unwind_protect in more places * Files affected: unwinddemo.cc, __ftp__.cc, graphics.cc, input.cc, interpreter.cc, mex.cc, oct-hist.cc, toplev.cc, urlwrite.cc, cdef-class.cc, ov-fcn-handle.cc, oct-parse.yy, pt-eval.cc, pt-jit.cc, url-transfer.cc, and url-transfer.h.
author John W. Eaton <jwe@octave.org>
date Sun, 03 Jan 2021 14:39:31 -0500
parents e274759bcb12
children 11343ca3c125
files examples/code/unwinddemo.cc libinterp/corefcn/__ftp__.cc libinterp/corefcn/graphics.cc libinterp/corefcn/input.cc libinterp/corefcn/interpreter.cc libinterp/corefcn/mex.cc libinterp/corefcn/oct-hist.cc libinterp/corefcn/toplev.cc libinterp/corefcn/urlwrite.cc libinterp/octave-value/cdef-class.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-jit.cc liboctave/util/url-transfer.cc liboctave/util/url-transfer.h
diffstat 16 files changed, 119 insertions(+), 169 deletions(-) [+]
line wrap: on
line diff
--- a/examples/code/unwinddemo.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/examples/code/unwinddemo.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -21,14 +21,16 @@
   NDArray a = args(0).array_value ();
   NDArray b = args(1).array_value ();
 
-  // Declare unwind_protect frame which lasts as long as
-  // the variable frame has scope.
-  octave::unwind_protect frame;
-  frame.add_fcn (set_liboctave_warning_handler,
-                 current_liboctave_warning_handler);
+  // Create unwind_action objects.  At the end of the enclosing scope,
+  // destructors for these objects will call the given functions with
+  // the specified arguments.
 
-  frame.add_fcn (set_liboctave_warning_with_id_handler,
-                 current_liboctave_warning_with_id_handler);
+  octave::unwind_action restore_warning_handler
+    (set_liboctave_warning_handler, current_liboctave_warning_handler);
+
+  octave::unwind_action restore_warning_with_id_handler
+    (set_liboctave_warning_with_id_handler,
+     current_liboctave_warning_with_id_handler);
 
   set_liboctave_warning_handler (my_err_handler);
   set_liboctave_warning_with_id_handler (my_err_with_id_handler);
--- a/libinterp/corefcn/__ftp__.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/__ftp__.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -52,12 +52,6 @@
 #include "unwind-prot.h"
 #include "url-handle-manager.h"
 
-static void
-delete_file (const std::string& file)
-{
-  octave::sys::unlink (file);
-}
-
 DEFMETHOD (__ftp__, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{handle} =} __ftp__ (@var{host})
@@ -503,16 +497,16 @@
               if (! ofile.is_open ())
                 error ("__ftp_mget__: unable to open file");
 
-              octave::unwind_protect_safe frame;
-
-              frame.add_fcn (delete_file, target + sv(i));
+              int(*unlink_fptr)(const std::string&) = octave::sys::unlink;
+              octave::unwind_action_safe delete_file
+                (unlink_fptr, target + sv(i));
 
               url_xfer.get (sv(i), ofile);
 
               ofile.close ();
 
               if (url_xfer.good ())
-                frame.discard ();
+                delete_file.set ();
             }
 
           if (! url_xfer.good ())
--- a/libinterp/corefcn/graphics.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/graphics.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -12253,9 +12253,8 @@
       else
         args(1) = Matrix ();
 
-      octave::unwind_protect_safe frame;
-
-      frame.add_method (this, &gh_manager::restore_gcbo);
+      octave::unwind_action_safe restore_gcbo_action
+        (&gh_manager::restore_gcbo, this);
 
       graphics_object go (get_object (h));
       if (go)
@@ -14409,7 +14408,9 @@
 
   caseless_str pname;
 
-  octave::unwind_protect frame;
+  octave::unwind_action cleanup_waitfor_id_action;
+  octave::unwind_action cleanup_waitfor_postset_listener_action;
+  octave::unwind_action cleanup_waitfor_predelete_listener_action;
 
   static uint32_t id_counter = 0;
   uint32_t id = 0;
@@ -14459,7 +14460,7 @@
           Cell listener (1, max_arg_index >= 2 ? 5 : 4);
 
           id = id_counter++;
-          frame.add_fcn (cleanup_waitfor_id, id);
+          cleanup_waitfor_id_action.set (cleanup_waitfor_id, id);
           waitfor_results[id] = false;
 
           listener(0) = wf_listener;
@@ -14485,8 +14486,9 @@
                 waitfor_results[id] = true;
               else
                 {
-
-                  frame.add_fcn (cleanup_waitfor_postset_listener, ov_listener);
+                  cleanup_waitfor_postset_listener_action.set
+                    (cleanup_waitfor_postset_listener, ov_listener);
+
                   go.add_property_listener (pname, ov_listener, GCB_POSTSET);
                   go.add_property_listener (pname, ov_listener, GCB_PERSISTENT);
 
@@ -14509,8 +14511,9 @@
 
                       octave_value ov_del_listener (del_listener);
 
-                      frame.add_fcn (cleanup_waitfor_predelete_listener,
-                                     ov_del_listener);
+                      cleanup_waitfor_predelete_listener_action.set
+                        (cleanup_waitfor_predelete_listener, ov_del_listener);
+
                       go.add_property_listener (pname, ov_del_listener,
                                                 GCB_PREDELETE);
                     }
--- a/libinterp/corefcn/input.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/input.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -193,8 +193,8 @@
 
             unwind_protect frame;
 
-            frame.add_method (es, &error_system::set_discard_warning_messages,
-                              es.discard_warning_messages ());
+            frame.add (&error_system::set_discard_warning_messages, &es,
+                       es.discard_warning_messages ());
 
             es.discard_warning_messages (true);
 
--- a/libinterp/corefcn/interpreter.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/interpreter.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -704,10 +704,8 @@
         // be evaluated from the normal interpreter loop where exceptions
         // are already handled.
 
-        unwind_protect frame;
-
-        frame.add_method (m_load_path, &load_path::set_add_hook,
-                          m_load_path.get_add_hook ());
+        unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path,
+                                        m_load_path.get_add_hook ());
 
         m_load_path.set_add_hook ([=] (const std::string& dir)
                                   { this->execute_pkg_add (dir); });
@@ -831,14 +829,13 @@
     {                                                                   \
       try                                                               \
         {                                                               \
-          unwind_protect frame;                                         \
+          unwind_action restore_debug_on_error                          \
+            (&error_system::set_debug_on_error, &m_error_system,        \
+             m_error_system.debug_on_error ());                        \
                                                                         \
-          frame.add_method (m_error_system,                             \
-                            &error_system::set_debug_on_error,          \
-                            m_error_system.debug_on_error ());          \
-          frame.add_method (m_error_system,                             \
-                            &error_system::set_debug_on_warning,        \
-                            m_error_system.debug_on_warning ());        \
+          unwind_action restore_debug_on_warning                        \
+            (&error_system::set_debug_on_warning, &m_error_system,      \
+             m_error_system.debug_on_warning ());                       \
                                                                         \
           m_error_system.debug_on_error (false);                        \
           m_error_system.debug_on_warning (false);                      \
@@ -1166,23 +1163,26 @@
 
     const cmdline_options& options = m_app_context->options ();
 
-    unwind_protect frame;
-
-    frame.add_method (this, &interpreter::interactive, m_interactive);
-
     string_vector args = options.all_args ();
 
-    frame.add_method (m_app_context, &application::intern_argv, args);
+    void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive;
+    unwind_action restore_interactive (interactive_fptr, this, m_interactive);
 
-    frame.add_method (this, &interpreter::intern_nargin, args.numel () - 1);
+    unwind_action restore_argv (&application::intern_argv, m_app_context, args);
+
+    unwind_action restore_nargin (&interpreter::intern_nargin, this,
+                                  args.numel () - 1);
 
-    frame.add_method (m_app_context,
-                      &application::program_invocation_name,
-                      application::program_invocation_name ());
+    void (application::*program_invocation_name_fptr) (const std::string&)
+      = &application::program_invocation_name;
+    unwind_action restore_program_invocation_name
+      (program_invocation_name_fptr, m_app_context,
+       application::program_invocation_name ());
 
-    frame.add_method (m_app_context,
-                      &application::program_name,
-                      application::program_name ());
+    void (application::*program_name_fptr) (const std::string&)
+      = &application::program_name;
+    unwind_action restore_program_name
+      (program_name_fptr, m_app_context, application::program_name ());
 
     m_interactive = false;
 
--- a/libinterp/corefcn/mex.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/mex.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -4607,8 +4607,8 @@
             {
               octave::tree_evaluator& tw = interp.get_evaluator ();
 
-              frame.add_method (tw, &octave::tree_evaluator::restore_frame,
-                                tw.current_call_stack_frame_number ());
+              frame.add (&octave::tree_evaluator::restore_frame, &tw,
+                         tw.current_call_stack_frame_number ());
 
               tw.goto_base_frame ();
             }
@@ -4672,8 +4672,8 @@
             {
               octave::tree_evaluator& tw = interp.get_evaluator ();
 
-              frame.add_method (tw, &octave::tree_evaluator::restore_frame,
-                                tw.current_call_stack_frame_number ());
+              frame.add (&octave::tree_evaluator::restore_frame, &tw,
+                         tw.current_call_stack_frame_number ());
 
               tw.goto_base_frame ();
             }
--- a/libinterp/corefcn/oct-hist.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/oct-hist.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -261,12 +261,6 @@
     return name;
   }
 
-  static void
-  unlink_cleanup (const char *file)
-  {
-    octave_unlink_wrapper (file);
-  }
-
   history_system::history_system (interpreter& interp)
     : m_interpreter (interp), m_input_from_tmp_file (false),
       m_timestamp_format_string (default_timestamp_format ())
@@ -502,12 +496,9 @@
 
     file.close ();
 
-    unwind_protect frame;
-
-    frame.add_fcn (unlink_cleanup, name.c_str ());
-    frame.protect_var (m_input_from_tmp_file);
-
-    m_input_from_tmp_file = true;
+    int(*unlink_fptr)(const std::string&) = octave::sys::unlink;
+    unwind_action unlink_action (unlink_fptr, name);
+    unwind_protect_var<bool> upv (m_input_from_tmp_file, true);
 
     // FIXME: instead of sourcing a file, we should just iterate through
     // the list of commands, parsing and executing them one at a time as
@@ -523,12 +514,9 @@
     if (name.empty ())
       return;
 
-    unwind_protect frame;
-
-    frame.add_fcn (unlink_cleanup, name.c_str ());
-    frame.protect_var (m_input_from_tmp_file);
-
-    m_input_from_tmp_file = true;
+    int(*unlink_fptr)(const std::string&) = octave::sys::unlink;
+    unwind_action unlink_action (unlink_fptr, name);
+    unwind_protect_var<bool> upv (m_input_from_tmp_file, true);
 
     // FIXME: instead of sourcing a file, we should just iterate through
     // the list of commands, parsing and executing them one at a time as
--- a/libinterp/corefcn/toplev.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/toplev.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -111,7 +111,7 @@
 
   octave::child_list& kids
     = octave::__get_child_list__ ("run_command_and_return_output");
-  frame.add_method (kids, &octave::child_list::remove, cmd->pid ());
+  frame.add (&octave::child_list::remove, kids, cmd->pid ());
 
   if (! *cmd)
     error ("system: unable to start subprocess for '%s'", cmd_str.c_str ());
--- a/libinterp/corefcn/urlwrite.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/corefcn/urlwrite.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -52,12 +52,6 @@
 #include "unwind-prot.h"
 #include "url-handle-manager.h"
 
-static void
-delete_file (const std::string& file)
-{
-  octave::sys::unlink (file);
-}
-
 DEFUN (urlwrite, args, nargout,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {} urlwrite (@var{url}, @var{localfile})
@@ -148,9 +142,8 @@
   if (! ofile.is_open ())
     error ("urlwrite: unable to open file");
 
-  octave::unwind_protect_safe frame;
-
-  frame.add_fcn (delete_file, filename);
+  int(*unlink_fptr)(const std::string&) = octave::sys::unlink;
+  octave::unwind_action_safe unlink_action (unlink_fptr, filename);
 
   octave::url_transfer url_xfer (url, ofile);
 
@@ -164,7 +157,7 @@
   ofile.close ();
 
   if (url_xfer.good ())
-    frame.discard ();
+    unlink_action.set ();
 
   if (nargout > 0)
     {
--- a/libinterp/octave-value/cdef-class.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/octave-value/cdef-class.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -864,12 +864,10 @@
     // this, we may pick up stray values from the current scope when
     // evaluating expressions found in things like attribute lists.
 
-    unwind_protect frame;
-
     tree_evaluator& tw = interp.get_evaluator ();
 
     tw.push_dummy_scope (full_class_name);
-    frame.add_method (tw, &tree_evaluator::pop_scope);
+    unwind_action pop_scope (&tree_evaluator::pop_scope, &tw);
 
     std::list<cdef_class> slist;
 
--- a/libinterp/octave-value/ov-fcn-handle.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -1919,8 +1919,6 @@
 
     std::streampos pos = is.tellg ();
 
-    unwind_protect_safe frame;
-
     // Set up temporary scope to use for evaluating the text that
     // defines the anonymous function.
 
@@ -1930,7 +1928,7 @@
     tree_evaluator& tw = interp.get_evaluator ();
 
     tw.push_dummy_scope (buf);
-    frame.add_method (tw, &tree_evaluator::pop_scope);
+    unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw);
 
     octave_idx_type len = 0;
 
@@ -2037,8 +2035,6 @@
     is.read (ctmp2, tmp);
     ctmp2[tmp] = 0;
 
-    unwind_protect_safe frame;
-
     // Set up temporary scope to use for evaluating the text that
     // defines the anonymous function.
 
@@ -2048,7 +2044,7 @@
     tree_evaluator& tw = interp.get_evaluator ();
 
     tw.push_dummy_scope (ctmp2);
-    frame.add_method (tw, &tree_evaluator::pop_scope);
+    unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw);
 
     if (len > 0)
       {
@@ -2353,8 +2349,6 @@
     H5Eset_auto (err_func, err_func_data);
 #endif
 
-    unwind_protect_safe frame;
-
     // Set up temporary scope to use for evaluating the text that
     // defines the anonymous function.
 
@@ -2364,7 +2358,7 @@
     tree_evaluator& tw = interp.get_evaluator ();
 
     tw.push_dummy_scope (fcn_tmp);
-    frame.add_method (tw, &tree_evaluator::pop_scope);
+    unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw);
 
     if (len > 0 && success)
       {
--- a/libinterp/parse-tree/oct-parse.yy	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/parse-tree/oct-parse.yy	Sun Jan 03 14:39:31 2021 -0500
@@ -2751,15 +2751,15 @@
             // the previous value of last_warning_message and skip the
             // conversion to a constant value.
 
-            unwind_protect frame;
-
             error_system& es = interp.get_error_system ();
 
-            frame.add_method (es, &error_system::set_last_warning_message,
-                              es.last_warning_message (""));
-
-            frame.add_method (es, &error_system::set_discard_warning_messages,
-                              es.discard_warning_messages (true));
+            unwind_action restore_last_warning_message
+              (&error_system::set_last_warning_message, &es,
+               es.last_warning_message (""));
+
+            unwind_action restore_discard_warning_messages
+              (&error_system::set_discard_warning_messages, &es,
+               es.discard_warning_messages (true));
 
             tree_evaluator& tw = interp.get_evaluator ();
 
@@ -4567,15 +4567,15 @@
             // the previous value of last_warning_message and skip the
             // conversion to a constant value.
 
-            unwind_protect frame;
-
             error_system& es = interp.get_error_system ();
 
-            frame.add_method (es, &error_system::set_last_warning_message,
-                              es.last_warning_message (""));
-
-            frame.add_method (es, &error_system::set_discard_warning_messages,
-                              es.discard_warning_messages (true));
+            unwind_action restore_last_warning_message
+              (&error_system::set_last_warning_message, &es,
+               es.last_warning_message (""));
+
+            unwind_action restore_discard_warning_messages
+              (&error_system::set_discard_warning_messages, &es,
+               es.discard_warning_messages (true));
 
             tree_evaluator& tw = interp.get_evaluator ();
 
--- a/libinterp/parse-tree/pt-eval.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -153,8 +153,8 @@
 
     bool silent = tw.quiet_breakpoint_flag (false);
 
-    frame.add_method (tw, &tree_evaluator::restore_frame,
-                      tw.current_call_stack_frame_number ());
+    frame.add (&tree_evaluator::restore_frame, &tw,
+               tw.current_call_stack_frame_number ());
 
     tw.goto_frame (tw.debug_frame ());
 
@@ -200,11 +200,8 @@
 
             evmgr.set_workspace ();
 
-            frame.add ([=, &evmgr] (void)
-                       {
-                         evmgr.execute_in_debugger_event (fcn_nm,
-                                                          curr_debug_line);
-                       });
+            frame.add (&event_manager::execute_in_debugger_event, &evmgr,
+                       fcn_nm, curr_debug_line);
 
             if (! silent)
               {
@@ -231,14 +228,15 @@
     if (m_level > 0)
       tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg;
 
-    frame.add_method (input_sys, &input_system::set_PS1, input_sys.PS1 ());
+    frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ());
     input_sys.PS1 (tmp_prompt);
 
     if (! m_interpreter.interactive ())
       {
-
-        frame.add_method (m_interpreter, &interpreter::interactive,
-                          m_interpreter.interactive ());
+        void (interpreter::*interactive_fptr) (bool)
+          = &interpreter::interactive;
+        frame.add (interactive_fptr, &m_interpreter,
+                   m_interpreter.interactive ());
 
         m_interpreter.interactive (true);
 
@@ -249,8 +247,10 @@
 
         if (app)
           {
-            frame.add_method (app, &application::forced_interactive,
-                              app->forced_interactive ());
+            void (application::*forced_interactive_fptr) (bool)
+              = &application::forced_interactive;
+            frame.add (forced_interactive_fptr, app,
+                       app->forced_interactive ());
 
             app->forced_interactive (true);
           }
@@ -793,24 +793,23 @@
   {
     unwind_protect frame;
 
-    frame.add_fcn (command_history::ignore_entries,
-                   command_history::ignoring_entries ());
+    frame.add (command_history::ignore_entries,
+               command_history::ignoring_entries ());
 
     command_history::ignore_entries (false);
 
-    frame.add_method (m_call_stack, &call_stack::restore_frame,
-                      m_call_stack.current_frame ());
+    frame.add (&call_stack::restore_frame, &m_call_stack,
+               m_call_stack.current_frame ());
 
     // Don't allow errors or warnings at the debug prompt to push us
     // into deeper levels of debugging.
 
     error_system& es = m_interpreter.get_error_system ();
 
-    frame.add_method (es, &error_system::set_debug_on_error,
-                      es.debug_on_error ());
-
-    frame.add_method (es, &error_system::set_debug_on_warning,
-                      es.debug_on_warning ());
+    frame.add (&error_system::set_debug_on_error, &es, es.debug_on_error ());
+
+    frame.add (&error_system::set_debug_on_warning, &es,
+               es.debug_on_warning ());
 
     es.debug_on_error (false);
     es.debug_on_warning (false);
@@ -1496,8 +1495,8 @@
 
     if (! context.empty ())
       {
-        frame.add_method (m_call_stack, &call_stack::restore_frame,
-                          m_call_stack.current_frame ());
+        frame.add (&call_stack::restore_frame, &m_call_stack,
+                   m_call_stack.current_frame ());
 
         if (context == "caller")
           m_call_stack.goto_caller_frame ();
@@ -3405,10 +3404,11 @@
     // We want to preserve the last location info for possible
     // backtracking.
 
-    frame.add_method (m_call_stack, &call_stack::set_line,
-                      m_call_stack.current_line ());
-    frame.add_method (m_call_stack, &call_stack::set_column,
-                      m_call_stack.current_column ());
+    frame.add (&call_stack::set_line, &m_call_stack,
+               m_call_stack.current_line ());
+
+    frame.add (&call_stack::set_column, &m_call_stack,
+               m_call_stack.current_column ());
 
     // Similarly, if we have seen a return or break statement, allow all
     // the cleanup code to run before returning or handling the break.
@@ -4056,8 +4056,8 @@
   void
   tree_evaluator::push_echo_state_cleanup (unwind_protect& frame)
   {
-    frame.add_method (this, &tree_evaluator::uwp_set_echo_state,
-                      m_echo_state, m_echo_file_name, m_echo_file_pos);
+    frame.add (&tree_evaluator::uwp_set_echo_state, this,
+               m_echo_state, m_echo_file_name, m_echo_file_pos);
   }
 
   bool tree_evaluator::maybe_push_echo_state_cleanup (void)
--- a/libinterp/parse-tree/pt-jit.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/libinterp/parse-tree/pt-jit.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -1234,9 +1234,8 @@
 
     for (size_t idx = 0; iter != arg_list->end (); ++idx, ++iter)
       {
-        unwind_protect frame;
-        frame.add_method (&m_end_context,
-                          &std::vector<jit_magic_end::context>::pop_back);
+        unwind_action pop_end_context
+          (&std::vector<jit_magic_end::context>::pop_back, &m_end_context));
 
         jit_magic_end::context ctx (m_factory, object, idx, narg);
         m_end_context.push_back (ctx);
--- a/liboctave/util/url-transfer.cc	Sun Jan 03 14:38:14 2021 -0500
+++ b/liboctave/util/url-transfer.cc	Sun Jan 03 14:39:31 2021 -0500
@@ -71,12 +71,6 @@
   { }
 
   void
-  base_url_transfer::delete_file (const std::string& file)
-  {
-    sys::unlink (file);
-  }
-
-  void
   base_url_transfer::mget_directory (const std::string& directory,
                                      const std::string& target)
   {
@@ -101,9 +95,7 @@
 
     if (good ())
       {
-        unwind_protect_safe frame;
-
-        frame.add_fcn (reset_path, this);
+        unwind_action_safe reset_path (&base_url_transfer::cwd, this, "..");
 
         string_vector sv = list ();
 
@@ -131,17 +123,15 @@
                     m_errmsg = "__ftp_mget__: unable to open file";
                     break;
                   }
-
-                unwind_protect_safe frame2;
-
-                frame2.add_fcn (delete_file, realfile);
+                int(*unlink_fptr)(const std::string&) = sys::unlink;
+                unwind_action_safe delete_file (unlink_fptr, realfile);
 
                 get (sv(i), ofile);
 
                 ofile.close ();
 
                 if (good ())
-                  frame2.discard ();
+                  delete_file.set ();
               }
 
             if (! good ())
@@ -169,9 +159,7 @@
 
     if (good ())
       {
-        unwind_protect_safe frame;
-
-        frame.add_fcn (reset_path, this);
+        unwind_action_safe reset_path (&base_url_transfer::cwd, this, "..");
 
         string_vector files;
         std::string msg;
--- a/liboctave/util/url-transfer.h	Sun Jan 03 14:38:14 2021 -0500
+++ b/liboctave/util/url-transfer.h	Sun Jan 03 14:39:31 2021 -0500
@@ -56,15 +56,6 @@
   OCTAVE_API
   base_url_transfer
   {
-  private:
-
-    static void delete_file (const std::string& file);
-
-    static void reset_path (base_url_transfer *curl_xfer)
-    {
-      curl_xfer->cwd ("..");
-    }
-
   public:
 
     friend class url_transfer;