diff --git a/Makefile.am b/Makefile.am index f3f53d5..4f8867b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -153,6 +153,7 @@ src_backend_libbackend_la_SOURCES = \ src/backend/concrete_simulation.cc \ src/backend/cpu_policies_gatekeeper.cc \ src/backend/cpu_policy.cc \ + src/backend/cpu_policy_exception.cc \ src/backend/cpu_policy_manager.cc \ src/backend/dynamic_process.cc \ src/backend/dynamic_request.cc \ @@ -203,6 +204,7 @@ pkginclude_HEADERS += \ config.h \ src/backend/cpu_policies_gatekeeper.hh \ src/backend/cpu_policy.hh \ + src/backend/cpu_policy_exception.hh \ src/backend/cpu_policy_manager.hh \ src/backend/environment.hh \ src/backend/global_preferences.hh \ diff --git a/glade/add-process-dialog.glade b/glade/add-process-dialog.glade index b3e4204..f699959 100644 --- a/glade/add-process-dialog.glade +++ b/glade/add-process-dialog.glade @@ -75,50 +75,6 @@ 11 9 - - - True - True - True - True - 0 - - True - - False - 17 - - - 1 - 2 - 1 - 2 - - - - - - - True - True - True - True - 0 - - True - - False - 17 - - - 1 - 2 - 2 - 3 - - - - True @@ -224,6 +180,48 @@ + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 1 1 inf 1 10 10 + + + 1 + 2 + 1 + 2 + + + + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 0 0 inf 1 10 10 + + + 1 + 2 + 2 + 3 + + + 0 diff --git a/glade/add-request-dialog.glade b/glade/add-request-dialog.glade index f5e255e..f1373b2 100644 --- a/glade/add-request-dialog.glade +++ b/glade/add-request-dialog.glade @@ -105,16 +105,16 @@ - + True True - True - True - 0 - - True - - False + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 0 0 inf 1 10 10 0 @@ -225,27 +225,6 @@ - - - True - True - True - True - 0 - - True - - False - - - 1 - 2 - 1 - 2 - - - - True @@ -261,6 +240,27 @@ fill + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 1 1 inf 1 10 10 + + + 1 + 2 + 1 + 2 + + + 0 diff --git a/glade/add-resource-dialog.glade b/glade/add-resource-dialog.glade index c6dd96d..e39612c 100644 --- a/glade/add-resource-dialog.glade +++ b/glade/add-resource-dialog.glade @@ -163,7 +163,7 @@ GTK_UPDATE_ALWAYS False False - 1 1 100 1 10 10 + 1 1 inf 1 10 10 1 @@ -212,7 +212,7 @@ GTK_UPDATE_ALWAYS False False - 1 0 100 1 10 10 + 0 0 inf 1 10 10 1 diff --git a/glade/add-thread-dialog.glade b/glade/add-thread-dialog.glade index e4fb4f3..7ce1313 100644 --- a/glade/add-thread-dialog.glade +++ b/glade/add-thread-dialog.glade @@ -153,28 +153,6 @@ - - - True - True - True - True - 0 - - True - - False - 17 - - - 1 - 2 - 3 - 4 - - - - True @@ -203,28 +181,6 @@ - - - True - True - True - True - 0 - - True - - False - 17 - - - 1 - 2 - 2 - 3 - - - - True @@ -254,16 +210,16 @@ - + True True - True - True - 0 - - True - - False + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 1 1 inf 1 10 10 1 @@ -273,6 +229,48 @@ + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 0 0 inf 1 10 10 + + + 1 + 2 + 2 + 3 + + + + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 0 0 inf 1 10 10 + + + 1 + 2 + 3 + 4 + + + 0 diff --git a/plugins/pyloader/src/ScriptAdapter.py b/plugins/pyloader/src/ScriptAdapter.py index 03f0091..ed7a59c 100644 --- a/plugins/pyloader/src/ScriptAdapter.py +++ b/plugins/pyloader/src/ScriptAdapter.py @@ -1,4 +1,4 @@ -import mutex, thread +import sys, mutex, thread import sgpem ## @brief This is an adapter class which acts as a proxy @@ -26,6 +26,8 @@ class ScriptAdapter : ## Var Testable syncronization object _g_mutex = mutex.mutex() + _g_last_exception = None + ## @brief Constructor of ScriptAdapter # # @param self The caller object @@ -38,15 +40,19 @@ class ScriptAdapter : # # @param self The caller object def async_configure(self): - self._g_mutex.lock(ScriptAdapter._wrap_configure, self ) + self._g_last_exception = None + self._g_mutex.lock(ScriptAdapter._wrap_configure, self ) def _wrap_configure(self): thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,)) def _wrap_configure_callback(self): # call configure method - self._policy.configure() - self._g_mutex.unlock() + try: + self._policy.configure() + except: + self._g_last_exception = sys.exc_value + self._g_mutex.unlock() ## @brief Asynchronously call Policy.sort_queue() @@ -56,6 +62,7 @@ class ScriptAdapter : # # @param self The caller object def async_sort_queue(self): + self._g_last_exception = None self._g_mutex.lock(ScriptAdapter._wrap_sort_queue, self) def _wrap_sort_queue(self): @@ -64,7 +71,11 @@ class ScriptAdapter : def _wrap_sort_queue_callback(self): # here we retrieve and pass the ready queue queue = sgpem.Scheduler.get_instance().get_ready_queue() - self._policy.sort_queue(queue) + + try: + self._policy.sort_queue(queue) + except: + self._g_last_exception = sys.exc_value self._g_mutex.unlock() @@ -72,26 +83,34 @@ class ScriptAdapter : # # @param self The caller object def async_is_preemptive(self): + self._g_last_exception = None self._g_mutex.lock(ScriptAdapter._wrap_is_preemptive, self) def _wrap_is_preemptive(self): thread.start_new_thread(ScriptAdapter._wrap_is_preemptive_callback, (self,)) def _wrap_is_preemptive_callback(self): - self._ret_val = self._policy.is_preemptive() + try: + self._ret_val = self._policy.is_preemptive() + except: + self._g_last_exception = sys.exc_value self._g_mutex.unlock() ## @brief Asynchronously call Policy.get_time_slice() # # @param self The caller object def async_get_time_slice(self): + self._g_last_exception = None self._g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self) def _wrap_get_time_slice(self): thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,)) def _wrap_get_time_slice_callback(self): - self._ret_val = self._policy.get_time_slice() + try: + self._ret_val = self._policy.get_time_slice() + except: + self._g_last_exception = sys.exc_value self._g_mutex.unlock() ## @brief Return the global shared variable with the methods' last return value @@ -100,3 +119,7 @@ class ScriptAdapter : def mutex_test_lock(self): return self._g_mutex.test() + + def get_last_exception(self): + return self._g_last_exception + diff --git a/plugins/pyloader/src/python_cpu_policy.cc b/plugins/pyloader/src/python_cpu_policy.cc index d9e86e9..fe40d47 100644 --- a/plugins/pyloader/src/python_cpu_policy.cc +++ b/plugins/pyloader/src/python_cpu_policy.cc @@ -40,7 +40,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio Py_DECREF(pLoadmeStr); if (pUserCPUPolicyModule == NULL) - throw MalformedPolicyException(get_exception_information().c_str()); + throw MalformedPolicyException(get_exception_information()); // Dictionary with defined ``symbols'' for .pyc file _upolicy_dict = PyModule_GetDict(pUserCPUPolicyModule); @@ -70,7 +70,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio Py_DECREF(pScriptAdapterModule); if (_adapter == NULL) - throw MalformedPolicyException(get_exception_information().c_str()); + throw MalformedPolicyException(get_exception_information()); // And now, who's your daddy, huh? } @@ -87,7 +87,7 @@ PythonCPUPolicy::~PythonCPUPolicy() } void -PythonCPUPolicy::activate() +PythonCPUPolicy::activate() throw(UserInterruptException, MalformedPolicyException) { // FIXME write the rest, taking away code from constructor @@ -107,7 +107,7 @@ PythonCPUPolicy::deactivate() void -PythonCPUPolicy::configure() throw(UserInterruptException) +PythonCPUPolicy::configure() throw(UserInterruptException, MalformedPolicyException) { PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL); Py_DECREF(retval); @@ -117,7 +117,7 @@ PythonCPUPolicy::configure() throw(UserInterruptException) void -PythonCPUPolicy::sort_queue() const throw(UserInterruptException) +PythonCPUPolicy::sort_queue() const throw(UserInterruptException, MalformedPolicyException) { PyObject* retval = PyObject_CallMethod(_adapter, "async_sort_queue", NULL); @@ -143,7 +143,7 @@ PythonCPUPolicy::get_name() const } bool -PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException) +PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException) { PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL); Py_DECREF(retval); @@ -160,7 +160,7 @@ PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException) int -PythonCPUPolicy::get_time_slice() const throw(UserInterruptException) +PythonCPUPolicy::get_time_slice() const throw(UserInterruptException, MalformedPolicyException) { PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL); @@ -181,7 +181,7 @@ PythonCPUPolicy::get_time_slice() const throw(UserInterruptException) void -PythonCPUPolicy::wait_unlock() const throw(UserInterruptException) +PythonCPUPolicy::wait_unlock() const throw(UserInterruptException, MalformedPolicyException) { PyThreadState* _save; int i = 0; // We give the sort_queue() three seconds max time, then... @@ -198,7 +198,7 @@ PythonCPUPolicy::wait_unlock() const throw(UserInterruptException) assert(retval); still_locked = PyObject_IsTrue(retval); Py_DECREF(retval); - + if (i++ > 12) /* waits for WAIT_FOR * 12 microseconds == 3 secs */ { PyThreadState_Clear(_save); @@ -207,13 +207,37 @@ PythonCPUPolicy::wait_unlock() const throw(UserInterruptException) Py_UNBLOCK_THREADS; PyEval_RestoreThread(_save); - + if(PyErr_Occurred() != NULL) + abort(); + throw UserInterruptException(_("User-defined policy is " "taking too long to terminate.")); } } while (still_locked); + // check if there were unhandled exception in the user-defined code + + PyObject* pException = PyObject_CallMethod(_adapter, "get_last_exception", NULL); + + if(pException != NULL) + { + if(pException != Py_None) + { + PyObject* pExceptStr = PyObject_Str(pException); + + string msg = _("unhandled exception in user policy: "); + msg += PyString_AsString(pExceptStr); + + Py_DECREF(pExceptStr); + Py_DECREF(pException); + + throw MalformedPolicyException(msg); + } + else + Py_DECREF(pException); + } + // What we should really do here: /* do { enable python threads @@ -260,6 +284,8 @@ PythonCPUPolicy::get_exception_information() if (pValue != NULL) Py_DECREF(pValue); if (pTraceback != NULL) Py_DECREF(pTraceback); + PyErr_Clear(); + return msg; } diff --git a/plugins/pyloader/src/python_cpu_policy.hh b/plugins/pyloader/src/python_cpu_policy.hh index 4c6f489..afb4cb8 100644 --- a/plugins/pyloader/src/python_cpu_policy.hh +++ b/plugins/pyloader/src/python_cpu_policy.hh @@ -51,12 +51,12 @@ namespace sgpem /** Calls the method \c async_configure */ - void configure() throw(UserInterruptException); + void configure() throw(UserInterruptException, MalformedPolicyException); /** Calls the method \c async_sort_queue */ - void sort_queue() const throw(UserInterruptException); + void sort_queue() const throw(UserInterruptException, MalformedPolicyException); /** \returns A textual description of this policy. @@ -69,14 +69,14 @@ namespace sgpem \returns \c TRUE if the policy is preemptive. \returns \c FALSE if the policy is not preemptive. */ - bool is_pre_emptive() const throw(UserInterruptException); + bool is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException); /** \returns The integer value of its time-slice. */ - int get_time_slice() const throw(UserInterruptException); + int get_time_slice() const throw(UserInterruptException, MalformedPolicyException); - void activate(); + void activate() throw(UserInterruptException, MalformedPolicyException); void deactivate(); @@ -84,7 +84,7 @@ namespace sgpem PythonCPUPolicy(const PythonCPUPolicy&); PythonCPUPolicy& operator=(const PythonCPUPolicy&); - void wait_unlock() const throw(UserInterruptException); + void wait_unlock() const throw(UserInterruptException, MalformedPolicyException); static std::string get_exception_information(); PyObject* _upolicy_dict; diff --git a/src/backend/cpu_policies_gatekeeper.cc b/src/backend/cpu_policies_gatekeeper.cc index 56659b1..69a0834 100644 --- a/src/backend/cpu_policies_gatekeeper.cc +++ b/src/backend/cpu_policies_gatekeeper.cc @@ -101,8 +101,18 @@ CPUPoliciesGatekeeper::activate_policy(History *history, CPUPolicy* policy) if (pos == end || pos->second != policy) { - _active_policies[history] = policy; - _active_policies[history]->activate(); + try + { + policy->activate(); + _active_policies[history] = policy; + } + catch(UserInterruptException e) + { + //FIXME what to do here??? + //probably throwing again a MalformedPolicyException + //maybe the best idea. or can we just fallback + //to the previous policy? + } } } diff --git a/src/backend/cpu_policy.hh b/src/backend/cpu_policy.hh index 636ee07..6660836 100644 --- a/src/backend/cpu_policy.hh +++ b/src/backend/cpu_policy.hh @@ -28,6 +28,7 @@ #include "policy_parameters.hh" #include "user_interrupt_exception.hh" +#include "malformed_policy_exception.hh" namespace sgpem { @@ -50,7 +51,7 @@ namespace sgpem Because it's a pure virtual method, must be re-implemented in concrete derived classes. */ - virtual void configure() throw(UserInterruptException) = 0; + virtual void configure() throw(UserInterruptException, MalformedPolicyException) = 0; /** Sort the \ref ReadyQueue object that contain all the Schedulable objects @@ -59,7 +60,7 @@ namespace sgpem Because it's a pure virtual method, must be re-implemented in concrete derived classes. */ - virtual void sort_queue() const throw(UserInterruptException) = 0; + virtual void sort_queue() const throw(UserInterruptException, MalformedPolicyException) = 0; /** Gets a string description of the policy. @@ -79,7 +80,7 @@ namespace sgpem in concrete derived classes. \return True if this policy is preemptible. */ - virtual bool is_pre_emptive() const throw(UserInterruptException) = 0; + virtual bool is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException) = 0; /** Gets the time quantum for the policy. @@ -88,9 +89,9 @@ namespace sgpem in concrete derived classes. \return Time quantum for the policy. */ - virtual int get_time_slice() const throw(UserInterruptException) = 0; + virtual int get_time_slice() const throw(UserInterruptException, MalformedPolicyException) = 0; - virtual void activate() = 0; + virtual void activate() throw(UserInterruptException, MalformedPolicyException) = 0; virtual void deactivate() = 0; diff --git a/src/backend/cpu_policy_exception.cc b/src/backend/cpu_policy_exception.cc new file mode 100644 index 0000000..759abfd --- /dev/null +++ b/src/backend/cpu_policy_exception.cc @@ -0,0 +1,31 @@ +// src/backend/cpu_policy_exception.cc - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// Warning! This exception will be thrown across different libraries. +// It could be necessary to do dynamic type-checking when +// catching it (with typeinfo). + +#include "malformed_policy_exception.hh" +using namespace sgpem; + +CPUPolicyException::CPUPolicyException(const std::string& msg) + : std::runtime_error(msg) +{} + diff --git a/src/backend/cpu_policy_exception.hh b/src/backend/cpu_policy_exception.hh new file mode 100644 index 0000000..b34f061 --- /dev/null +++ b/src/backend/cpu_policy_exception.hh @@ -0,0 +1,43 @@ +// src/backend/cpu_policy_exception.hh - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// This file is part of SGPEMv2. +// +// This is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// SGPEMv2 is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SGPEMv2; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// Warning! This exception will be thrown across different libraries. +// It could be necessary to do dynamic type-checking when +// catching it (with typeinfo). + +#ifndef CPU_POLICY_EXCEPTION +#define CPU_POLICY_EXCEPTION 1 + +#include "config.h" + +#include + +namespace sgpem +{ + class CPUPolicyException; + + class SG_DLLEXPORT CPUPolicyException : public std::runtime_error + { + public: + explicit CPUPolicyException(const std::string& msg = ""); + }; +} //~ namespace sgpem + +#endif diff --git a/src/backend/malformed_policy_exception.cc b/src/backend/malformed_policy_exception.cc index 2ed5369..2244548 100644 --- a/src/backend/malformed_policy_exception.cc +++ b/src/backend/malformed_policy_exception.cc @@ -25,8 +25,7 @@ #include "malformed_policy_exception.hh" using namespace sgpem; -MalformedPolicyException::MalformedPolicyException(const char* msg) - : std::runtime_error(msg) +MalformedPolicyException::MalformedPolicyException(const std::string& msg) + : CPUPolicyException(msg) {} -MalformedPolicyException::~MalformedPolicyException() throw() {} diff --git a/src/backend/malformed_policy_exception.hh b/src/backend/malformed_policy_exception.hh index 36e5fec..1f0e176 100644 --- a/src/backend/malformed_policy_exception.hh +++ b/src/backend/malformed_policy_exception.hh @@ -27,19 +27,16 @@ #include "config.h" -#include +#include "cpu_policy_exception.hh" namespace sgpem { class MalformedPolicyException; - class SG_DLLEXPORT MalformedPolicyException : public std::runtime_error + class SG_DLLEXPORT MalformedPolicyException : public CPUPolicyException { public: - MalformedPolicyException(const char* msg = ""); - virtual ~MalformedPolicyException() throw (); - - private: + explicit MalformedPolicyException(const std::string& msg = ""); }; } //~ namespace sgpem diff --git a/src/backend/null_policy_exception.cc b/src/backend/null_policy_exception.cc index 8357c49..d12c286 100644 --- a/src/backend/null_policy_exception.cc +++ b/src/backend/null_policy_exception.cc @@ -29,4 +29,3 @@ NullPolicyException::NullPolicyException(const char* msg) : std::runtime_error(msg) {} -NullPolicyException::~NullPolicyException() throw() {} diff --git a/src/backend/null_policy_exception.hh b/src/backend/null_policy_exception.hh index cfccec0..b0164f1 100644 --- a/src/backend/null_policy_exception.hh +++ b/src/backend/null_policy_exception.hh @@ -37,9 +37,6 @@ namespace sgpem { public: NullPolicyException(const char* msg = ""); - virtual ~NullPolicyException() throw (); - - private: }; } //~ namespace sgpem diff --git a/src/backend/user_interrupt_exception.cc b/src/backend/user_interrupt_exception.cc index 60230cc..87c7210 100644 --- a/src/backend/user_interrupt_exception.cc +++ b/src/backend/user_interrupt_exception.cc @@ -26,7 +26,6 @@ using namespace sgpem; UserInterruptException::UserInterruptException(const char* msg) - : std::runtime_error(msg) + : CPUPolicyException(msg) {} -UserInterruptException::~UserInterruptException() throw() {} diff --git a/src/backend/user_interrupt_exception.hh b/src/backend/user_interrupt_exception.hh index d3d21de..fccfc51 100644 --- a/src/backend/user_interrupt_exception.hh +++ b/src/backend/user_interrupt_exception.hh @@ -26,6 +26,7 @@ #define USER_INTERRUPT_EXCEPTION 1 #include "config.h" +#include "cpu_policy_exception.hh" #include @@ -33,13 +34,10 @@ namespace sgpem { class UserInterruptException; - class SG_DLLEXPORT UserInterruptException : public std::runtime_error + class SG_DLLEXPORT UserInterruptException : public CPUPolicyException { public: - UserInterruptException(const char* msg = ""); - virtual ~UserInterruptException() throw (); - - private: + explicit UserInterruptException(const char* msg = ""); }; } //~ namespace sgpem