tags 378152 + patch fixed-upstream pending
thanks

Roger Leigh <[EMAIL PROTECTED]> writes:

> The terminal settings are not being restored on exit (either
> on sucess or failure).  This looks like a recent regression with
> the splitting up of main().  exit() should not be called from
> any subclass of schroot_base::main()?

The attached patch fixes this by removing all but one exit point in
each binary.  This ensures the terminal restore is in the exit path
under all conditions.


-- 
  .''`.  Roger Leigh
 : :' :  Debian GNU/Linux             http://people.debian.org/~rleigh/
 `. `'   Printing on GNU/Linux?       http://gutenprint.sourceforge.net/
   `-    GPG Public Key: 0x25BFB848   Please sign and encrypt your mail.
Index: schroot/schroot-base-main.cc
===================================================================
--- schroot/schroot-base-main.cc	(revision 854)
+++ schroot/schroot-base-main.cc	(working copy)
@@ -160,11 +160,6 @@
 
       exit(EXIT_FAILURE);
     }
-  catch (...)
-    {
-      sbuild::log_error() << _("An unknown exception occured") << endl;
-      exit(EXIT_FAILURE);
-    }
 }
 
 /*
Index: schroot/schroot-main-base.cc
===================================================================
--- schroot/schroot-main-base.cc	(revision 854)
+++ schroot/schroot-main-base.cc	(working copy)
@@ -38,6 +38,31 @@
 using boost::format;
 using namespace schroot;
 
+namespace
+{
+
+  typedef std::pair<main_base::error_code,const char *> emap;
+
+  /**
+   * This is a list of the supported error codes.  It's used to
+   * construct the real error codes map.
+   */
+  emap init_errors[] =
+    {
+      emap(main_base::CHROOTS_NOTFOUND, N_("%1%: Chroots not found")),
+      emap(main_base::CHROOT_NOTDEFINED,
+	   N_("The specified chroots are not defined in '%1%'")),
+      emap(main_base::CHROOT_NOTFOUND,  N_("%1%: Chroot not found"))
+    };
+
+}
+
+template<>
+sbuild::error<main_base::error_code>::map_type
+sbuild::error<main_base::error_code>::error_strings
+(init_errors,
+ init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
+
 main_base::main_base (std::string const& program_name,
 		      std::string const& program_usage,
 		      options_base::ptr& options):
@@ -99,13 +124,19 @@
 
       if (!invalid_chroots.empty())
 	{
+	  std::string invalid_list;
 	  for (sbuild::string_list::const_iterator chroot =
 		 invalid_chroots.begin();
 	       chroot != invalid_chroots.end();
 	       ++chroot)
-	    sbuild::log_error() << format(_("%1%: No such chroot")) % *chroot
-				<< endl;
-	  exit(EXIT_FAILURE);
+	    {
+	      invalid_list += *chroot;
+	      if (chroot + 1 != invalid_chroots.end())
+		invalid_list += ", ";
+	    }
+	  throw error(invalid_list,
+		      (invalid_chroots.size() == 1)
+		      ? CHROOT_NOTFOUND : CHROOTS_NOTFOUND);
 	}
       ret = this->options->chroots;
     }
@@ -135,13 +166,13 @@
   if (this->options->action == options_base::ACTION_HELP)
     {
       action_help(std::cout);
-      exit(EXIT_SUCCESS);
+      return EXIT_SUCCESS;
     }
 
   if (this->options->action == options_base::ACTION_VERSION)
     {
       action_version(std::cout);
-      exit(EXIT_SUCCESS);
+      return EXIT_SUCCESS;
     }
 
   /* Initialise chroot configuration. */
@@ -169,46 +200,31 @@
   if (this->options->action == options_base::ACTION_LIST)
     {
       action_list();
-      exit(EXIT_SUCCESS);
+      return EXIT_SUCCESS;
     }
 
   /* Get list of chroots to use */
   chroots = get_chroot_options();
   if (this->chroots.empty())
-    {
-      sbuild::log_error()
-	<< format(_("The specified chroots are not defined in '%1%'"))
-	% SCHROOT_CONF
-	<< endl;
-      exit (EXIT_FAILURE);
-    }
+    throw error(SCHROOT_CONF, CHROOT_NOTDEFINED);
 
   /* Print chroot information for specified chroots. */
   if (this->options->action == options_base::ACTION_INFO)
     {
       action_info();
-      exit (EXIT_SUCCESS);
+      return EXIT_SUCCESS;
     }
   if (this->options->action == options_base::ACTION_LOCATION)
     {
       action_location();
-      exit (EXIT_SUCCESS);
+      return EXIT_SUCCESS;
     }
   if (this->options->action == options_base::ACTION_CONFIG)
     {
       action_config();
-      exit (EXIT_SUCCESS);
+      return EXIT_SUCCESS;
     }
 
-  if (this->options->action == options_base::ACTION_SESSION_BEGIN &&
-      this->chroots.size() != 1)
-    {
-      sbuild::log_error()
-	<< _("Only one chroot may be specified when beginning a session")
-	<< endl;
-      exit (EXIT_FAILURE);
-    }
-
   /* Create a session. */
   sbuild::session::operation sess_op(sbuild::session::OPERATION_AUTOMATIC);
   if (this->options->action == options_base::ACTION_SESSION_BEGIN)
@@ -255,9 +271,9 @@
     }
 
   if (this->session)
-    exit(this->session->get_child_status());
+    return this->session->get_child_status();
   else
-    exit(EXIT_FAILURE);
+    return EXIT_FAILURE;
 }
 
 /*
Index: schroot/schroot-main-base.h
===================================================================
--- schroot/schroot-main-base.h	(revision 846)
+++ schroot/schroot-main-base.h	(working copy)
@@ -23,6 +23,8 @@
 #include <schroot/schroot-base-main.h>
 #include <schroot/schroot-options-base.h>
 
+#include <sbuild/sbuild-custom-error.h>
+
 namespace schroot
 {
 
@@ -34,6 +36,17 @@
   class main_base : public schroot_base::main
   {
   public:
+    /// Error codes.
+    enum error_code
+      {
+	CHROOTS_NOTFOUND,       ///< Chroots not found.
+	CHROOT_NOTDEFINED,      ///< The specified chroots are not defined.
+	CHROOT_NOTFOUND         ///< Chroot not found.
+      };
+
+    /// Exception type.
+    typedef sbuild::custom_error<error_code> error;
+
     /**
      * The constructor.
      *
Index: schroot/schroot-releaselock-main.h
===================================================================
--- schroot/schroot-releaselock-main.h	(revision 846)
+++ schroot/schroot-releaselock-main.h	(working copy)
@@ -23,6 +23,8 @@
 #include <schroot/schroot-base-main.h>
 #include <schroot/schroot-releaselock-options.h>
 
+#include <sbuild/sbuild-custom-error.h>
+
 namespace schroot_releaselock
 {
 
@@ -32,6 +34,18 @@
   class main : public schroot_base::main
   {
   public:
+    /// Error codes.
+    enum error_code
+      {
+	DEVICE_NOTBLOCK, ///< File is not a block device.
+	DEVICE_OWNED,    ///< Failed to release device lock (lock held by PID).
+	DEVICE_RELEASE,  ///< Failed to release device lock.
+	DEVICE_STAT      ///< Failed to stat device.
+      };
+
+    /// Exception type.
+    typedef sbuild::custom_error<error_code> error;
+
     /**
      * The constructor.
      *
Index: schroot/schroot-options-base.cc
===================================================================
--- schroot/schroot-options-base.cc	(revision 846)
+++ schroot/schroot-options-base.cc	(working copy)
@@ -155,7 +155,7 @@
       this->load_chroots = true;
       this->load_sessions = false;
       if (this->chroots.size() != 1 || all_used())
-	throw opt::validation_error(_("Only one chroot may be specified when recovering, running or ending a session"));
+	throw opt::validation_error(_("Only one chroot may be specified when beginning a session"));
 
       this->all = this->all_chroots = this->all_sessions = false;
       break;
Index: schroot/schroot-releaselock-main.cc
===================================================================
--- schroot/schroot-releaselock-main.cc	(revision 854)
+++ schroot/schroot-releaselock-main.cc	(working copy)
@@ -39,6 +39,31 @@
 using boost::format;
 using namespace schroot_releaselock;
 
+namespace
+{
+
+  typedef std::pair<main::error_code,const char *> emap;
+
+  /**
+   * This is a list of the supported error codes.  It's used to
+   * construct the real error codes map.
+   */
+  emap init_errors[] =
+    {
+      emap(main::DEVICE_NOTBLOCK, N_("File is not a block device")),
+      emap(main::DEVICE_OWNED,    N_("Failed to release device lock (lock held by PID %4%")),
+      emap(main::DEVICE_RELEASE,  N_("Failed to release device lock")),
+      emap(main::DEVICE_STAT,     N_("Failed to stat device"))
+};
+
+}
+
+template<>
+sbuild::error<main::error_code>::map_type
+sbuild::error<main::error_code>::error_strings
+(init_errors,
+ init_errors + (sizeof(init_errors) / sizeof(init_errors[0])));
+
 main::main (options::ptr& options):
   schroot_base::main("schroot-releaselock",
 		     _("[OPTION...] - release a device lock"),
@@ -63,38 +88,16 @@
   struct stat statbuf;
 
   if (stat(this->options->device.c_str(), &statbuf) == -1)
-    {
-      sbuild::log_error()
-	<< format(_("Failed to stat device '%1%': %2%"))
-	% this->options->device % strerror(errno)
-	<< endl;
-      exit (EXIT_FAILURE);
-    }
+    throw error(this->options->device, DEVICE_STAT, strerror(errno));
+
   if (!S_ISBLK(statbuf.st_mode))
-    {
-      sbuild::log_error()
-	<< format(_("'%1%' is not a block device")) % this->options->device
-	<< endl;
-      exit (EXIT_FAILURE);
-    }
+    throw error(this->options->device, DEVICE_NOTBLOCK);
 
   pid_t status = dev_unlock(this->options->device.c_str(), this->options->pid);
   if (status < 0) // Failure
-    {
-      sbuild::log_error()
-	<< format(_("%1%: failed to release device lock"))
-	% this->options->device
-	<< endl;
-      exit (EXIT_FAILURE);
-    }
+    throw error(this->options->device, DEVICE_RELEASE);
   else if (status > 0) // Owned
-    {
-      sbuild::log_error()
-	<< format(_("%1%: failed to release device lock owned by pid %2%"))
-	% this->options->device % status
-	<< endl;
-      exit (EXIT_FAILURE);
-    }
+    throw error(this->options->device, DEVICE_OWNED, status);
 }
 
 int
Index: debian/changelog
===================================================================
--- debian/changelog	(revision 846)
+++ debian/changelog	(working copy)
@@ -10,6 +10,8 @@
     single command, separated by spaces.  This restores compatibility with
     dchroot 0.13 and earlier (Closes: #378028).  Thanks to David Liontooth
     for reporting this.
+  * Terminal settings are correctly restored under all normal exit
+    conditions (Closes: #378152).
   * debian/schroot.docs: Add the contents of debian/docs.
   * debian/docs: Remove.
   * debian/rules:
@@ -20,7 +22,7 @@
   * debian/dchroot-dsa.preinst: New file.  Remove
     /usr/share/doc/dchroot-dsa.
 
- -- Roger Leigh <[EMAIL PROTECTED]>  Thu, 13 Jul 2006 13:22:20 +0100
+ -- Roger Leigh <[EMAIL PROTECTED]>  Fri, 14 Jul 2006 14:43:50 +0100
 
 schroot (0.99.2-1) unstable; urgency=low
 
Index: sbuild/sbuild-session.cc
===================================================================
--- sbuild/sbuild-session.cc	(revision 854)
+++ sbuild/sbuild-session.cc	(working copy)
@@ -997,7 +997,7 @@
     }
 
   /* This should never be reached */
-  exit(EXIT_FAILURE);
+  _exit(EXIT_FAILURE);
 }
 
 void
@@ -1087,7 +1087,7 @@
 	{
 	  log_error() << e.what() << endl;
 	}
-      exit (EXIT_FAILURE);
+      _exit (EXIT_FAILURE);
     }
   else
     {
Index: sbuild/sbuild-run-parts.cc
===================================================================
--- sbuild/sbuild-run-parts.cc	(revision 854)
+++ sbuild/sbuild-run-parts.cc	(working copy)
@@ -179,7 +179,7 @@
       exec(this->directory + '/' + file, command, env);
       error e(file, EXEC, strerror(errno));
       log_error() << e.what() << std::endl;
-      exit(EXIT_FAILURE);
+      _exit(EXIT_FAILURE);
     }
   else
     {
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 855)
+++ ChangeLog	(working copy)
@@ -1,5 +1,30 @@
 2006-07-14  Roger Leigh  <[EMAIL PROTECTED]>
 
+	* debian/changelog: Close #378152.
+
+	* Having a single exit point now means terminal settings are
+	always restored correctly.
+
+	* sbuild/sbuild-run-parts.cc: Use _exit rather than exit when
+	terminating a child process when execve has failed.
+
+	* sbuild/sbuild-session.cc: Use _exit rather than exit when
+	terminating a child process when execve has failed.
+
+	* schroot/schroot-releaselock-main.(cc|h): Add error_code enum and
+	error typedef for sbuild::custom_error.  Throw error in place of
+	exiting with EXIT_FAILURE.
+
+	* schroot/schroot-main-base.(cc|h): Add error_code enum and error
+	typedef for sbuild::custom_error.  Throw error in place of exiting
+	with EXIT_FAILURE.  Don't ever exit successfully; return a success
+	status.
+
+	* schroot/schroot-base-main.cc (run): Don't catch "..."; it's
+	handled by the main() stubs.
+
+2006-07-14  Roger Leigh  <[EMAIL PROTECTED]>
+
 	* sbuild/sbuild-chroot-directory.cc (setup_env): Remove.
 	CHROOT_LOCATION is already set in the parent class.
 

Attachment: pgp2H67pglsyk.pgp
Description: PGP signature

Reply via email to