Index: src/sas/sascalc/data_util/calcthread.py
===================================================================
--- src/sas/sascalc/data_util/calcthread.py	(revision b699768550de9d4b35b087234ec1d2a461922bab)
+++ src/sas/sascalc/data_util/calcthread.py	(revision 934ce6493af6e904cf20f2500ef522b42192adfd)
@@ -119,5 +119,6 @@
 
     def __init__(self, completefn=None, updatefn=None,
-                 yieldtime=0.01, worktime=0.01):
+                 yieldtime=0.01, worktime=0.01,
+                 exception_handler=None):
         """Prepare the calculator"""
         self.yieldtime     = yieldtime
@@ -125,4 +126,5 @@
         self.completefn    = completefn
         self.updatefn      = updatefn
+        self.exception_handler = exception_handler
         self._interrupting = False
         self._running      = False
@@ -199,5 +201,4 @@
 
     def update(self, **kwargs):
-
         """Update GUI with the lastest results from the current work unit."""
         if self.updatefn != None and clock() > self._time_for_update:
@@ -225,5 +226,24 @@
         """Perform a work unit.  The subclass will provide details of
         the arguments."""
-        raise NotImplemented, "Calculation thread needs compute method"
+        raise NotImplemented("Calculation thread needs compute method")
+
+    def exception(self):
+        """
+        An exception occurred during computation, so call the exception handler
+        if there is one.  If not, then log the exception and continue.
+        """
+        # If we have an exception handler, let it try to handle the exception.
+        # If it fails fall through to log the failure to handle the exception
+        # (the original exception will be lost).  If there is no exception
+        # handler, just log the exception in compute that we are responding to.
+        if self.exception_handler:
+            try:
+                self.exception_handler(*sys.exc_info())
+                return
+            except Exception:
+                pass
+        import logging
+        logging.error(traceback.format_exc())
+        #print 'CalcThread exception',
 
     def _run(self):
@@ -250,6 +270,5 @@
                 pass
             except:
-                traceback.print_exc()
-                #print 'CalcThread exception',
+                self.exception()
         self._running = False
 
Index: src/sas/sasgui/perspectives/fitting/fitpage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpage.py	(revision cb4ef58d8aabd8393aae14823d3fa98d1ba0c1a2)
+++ src/sas/sasgui/perspectives/fitting/fitpage.py	(revision 934ce6493af6e904cf20f2500ef522b42192adfd)
@@ -1330,6 +1330,5 @@
                                               qmin=float(self.qmin_x),
                                               qmax=float(self.qmax_x),
-                                              enable_smearer=enable_smearer,
-                                              draw=True)
+                                              enable_smearer=enable_smearer)
                 if flag:
                     #self.compute_chisqr(smearer= temp_smearer)
@@ -2606,6 +2605,5 @@
                      qmin=float(self.qmin_x),
                      qmax=float(self.qmax_x),
-                     enable_smearer=enable_smearer,
-                     draw=True)
+                     enable_smearer=enable_smearer)
 
         self.state.enable_smearer = self.enable_smearer.GetValue()
Index: src/sas/sasgui/perspectives/fitting/fitting.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitting.py	(revision 243fbc08b5507d76300536ef5949cadf6da173c0)
+++ src/sas/sasgui/perspectives/fitting/fitting.py	(revision 934ce6493af6e904cf20f2500ef522b42192adfd)
@@ -19,5 +19,5 @@
 import time
 from copy import deepcopy
-import models
+import traceback
 
 from sas.sascalc.dataloader.loader import Loader
@@ -45,4 +45,6 @@
 from sas.sasgui.guiframe.gui_manager import MDIFrame
 from sas.sasgui.guiframe.documentation_window import DocumentationWindow
+
+from . import models
 
 MAX_NBR_DATA = 4
@@ -260,6 +262,6 @@
                 msg += "and try it again."
                 wx.MessageBox(msg, 'Info')
-                #wx.PostEvent(self.parent, StatusEvent(status=msg, type='stop',
-                #                                      info='warning'))
+                #evt = StatusEvent(status=msg, type='stop', info='warning')
+                #wx.PostEvent(self.parent, evt)
             else:
                 self.delete_menu.Delete(event_id)
@@ -268,6 +270,6 @@
                         self.edit_menu.DeleteItem(item)
                         msg = "The custom model, %s, has been deleted." % label
-                        wx.PostEvent(self.parent, StatusEvent(status=msg,
-                                                type='stop', info='info'))
+                        evt = StatusEvent(status=msg, type='stop', info='info')
+                        wx.PostEvent(self.parent, evt)
                         break
         except:
@@ -579,7 +581,7 @@
             except:
                 msg = "Fitting: cannot deal with the theory received"
+                evt = StatusEvent(status=msg, info="error")
                 logging.error("set_theory " + msg + "\n" + str(sys.exc_value))
-                wx.PostEvent(self.parent,
-                             StatusEvent(status=msg, info="error"))
+                wx.PostEvent(self.parent, evt)
 
     def set_state(self, state=None, datainfo=None, format=None):
@@ -968,7 +970,6 @@
                     if not page.param_toFit:
                         msg = "No fitting parameters for %s" % page.window_caption
-                        wx.PostEvent(page.parent.parent,
-                                     StatusEvent(status=msg, info="error",
-                                                 type="stop"))
+                        evt = StatusEvent(status=msg, info="error", type="stop")
+                        wx.PostEvent(page.parent.parent, evt)
                         return False
                     if not page._update_paramv_on_fit():
@@ -976,7 +977,6 @@
                         msg += " invalid in %s" % \
                                     page.window_caption
-                        wx.PostEvent(page.parent.parent,
-                                     StatusEvent(status=msg, info="error",
-                                     type="stop"))
+                        evt = StatusEvent(status=msg, info="error", type="stop")
+                        wx.PostEvent(page.parent.parent, evt)
                         return False
 
@@ -999,12 +999,12 @@
             except KeyboardInterrupt:
                 msg = "Fitting terminated"
-                wx.PostEvent(self.parent, StatusEvent(status=msg, info="info",
-                                                      type="stop"))
+                evt = StatusEvent(status=msg, info="info", type="stop")
+                wx.PostEvent(self.parent, evt)
                 return True
             except:
                 raise
                 msg = "Fitting error: %s" % str(sys.exc_value)
-                wx.PostEvent(self.parent, StatusEvent(status=msg, info="error",
-                                                      type="stop"))
+                evt = StatusEvent(status=msg, info="error", type="stop")
+                wx.PostEvent(self.parent, evt)
                 return False
         ## If a thread is already started, stop it
@@ -1101,10 +1101,10 @@
             # add data associated to the page created
             if page != None:
-                wx.PostEvent(self.parent, StatusEvent(status="Page Created",
-                                               info="info"))
+                evt = StatusEvent(status="Page Created", info="info")
+                wx.PostEvent(self.parent, evt)
             else:
                 msg = "Page was already Created"
-                wx.PostEvent(self.parent, StatusEvent(status=msg,
-                                                       info="warning"))
+                evt = StatusEvent(status=msg, info="warning")
+                wx.PostEvent(self.parent, evt)
         except:
             msg = "Creating Fit page: %s" % sys.exc_value
@@ -1268,6 +1268,6 @@
         msg = "Fit completed on %s \n" % str_time
         msg += "Duration time: %s s.\n" % str(elapsed)
-        wx.PostEvent(self.parent, StatusEvent(status=msg, info="info",
-                                              type="stop"))
+        evt = StatusEvent(status=msg, info="info", type="stop")
+        wx.PostEvent(self.parent, evt)
 
         if batch_outputs is None:
@@ -1419,6 +1419,6 @@
                                          batch_inputs=batch_inputs)
 
-        wx.PostEvent(self.parent, StatusEvent(status=msg, error="info",
-                                              type="stop"))
+        evt = StatusEvent(status=msg, error="info", type="stop")
+        wx.PostEvent(self.parent, evt)
         # Remove parameters that are not shown
         cpage = self.fit_panel.get_page_by_id(uid)
@@ -1499,6 +1499,6 @@
         msg = "Fit completed on %s \n" % str_time
         msg += "Duration time: %s s.\n" % str(elapsed)
-        wx.PostEvent(self.parent, StatusEvent(status=msg, info="info",
-                                                      type="stop"))
+        evt = StatusEvent(status=msg, info="info", type="stop")
+        wx.PostEvent(self.parent, evt)
         wx.PostEvent(self.result_panel, PlotResultEvent(result=result))
         wx.CallAfter(self._update_fit_button, page_id)
@@ -1524,8 +1524,6 @@
                     not numpy.all(numpy.isfinite(res.pvec)):
                     msg = "Fitting did not converge!!!"
-                    wx.PostEvent(self.parent,
-                             StatusEvent(status=msg,
-                                         info="warning",
-                                         type="stop"))
+                    evt = StatusEvent(status=msg, info="warning", type="stop")
+                    wx.PostEvent(self.parent, evt)
                     wx.CallAfter(self._update_fit_button, page_id)
                 else:
@@ -1551,12 +1549,10 @@
                     except KeyboardInterrupt:
                         msg = "Singular point: Fitting Stoped."
-                        wx.PostEvent(self.parent, StatusEvent(status=msg,
-                                                              info="info",
-                                                              type="stop"))
+                        evt = StatusEvent(status=msg, info="info", type="stop")
+                        wx.PostEvent(self.parent, evt)
                     except:
                         msg = "Singular point: Fitting Error occurred."
-                        wx.PostEvent(self.parent, StatusEvent(status=msg,
-                                                              info="error",
-                                                              type="stop"))
+                        evt = StatusEvent(status=msg, info="error", type="stop")
+                        wx.PostEvent(self.parent, evt)
 
         except:
@@ -1564,6 +1560,6 @@
                    % sys.exc_value)
             #import traceback; msg = "\n".join((traceback.format_exc(), msg))
-            wx.PostEvent(self.parent, StatusEvent(status=msg, info="warning",
-                                                  type="stop"))
+            evt = StatusEvent(status=msg, info="warning", type="stop")
+            wx.PostEvent(self.parent, evt)
 
     def _update_fit_button(self, page_id):
@@ -1602,6 +1598,5 @@
         ## post a message to status bar
         msg = "Set Chain Fitting: %s" % str(not self.batch_reset_flag)
-        wx.PostEvent(self.parent,
-                     StatusEvent(status=msg))
+        wx.PostEvent(self.parent, StatusEvent(status=msg))
 
 
@@ -1749,11 +1744,19 @@
             raise
 
+    def _calc_exception(self, etype, value, tb):
+        """
+        Handle exception from calculator by posting it as an error.
+        """
+        logging.error("".join(traceback.format_exception(etype, value, tb)))
+        msg = traceback.format_exception(etype, value, tb, limit=1)
+        evt = StatusEvent(status="".join(msg), type="stop", info="error")
+        wx.PostEvent(self.parent, evt)
+
     def _update2D(self, output, time=None):
         """
         Update the output of plotting model
         """
-        wx.PostEvent(self.parent, StatusEvent(status="Plot \
-        #updating ... ", type="update"))
-        #self.ready_fit()
+        msg = "Plot updating ... "
+        wx.PostEvent(self.parent, StatusEvent(msg, type="update"))
 
     def _complete2D(self, image, data, model, page_id, elapsed, index, qmin,
@@ -1861,15 +1864,17 @@
                     time.sleep(0.1)
             self.calc_2D = Calc2D(model=model,
-                                    data=data,
-                                    page_id=page_id,
-                                    smearer=smearer,
-                                    qmin=qmin,
-                                    qmax=qmax,
-                                    weight=weight,
-                                    fid=fid,
-                                    toggle_mode_on=toggle_mode_on,
-                                    state=state,
-                                    completefn=self._complete2D,
-                                    update_chisqr=update_chisqr, source=source)
+                                  data=data,
+                                  page_id=page_id,
+                                  smearer=smearer,
+                                  qmin=qmin,
+                                  qmax=qmax,
+                                  weight=weight,
+                                  fid=fid,
+                                  toggle_mode_on=toggle_mode_on,
+                                  state=state,
+                                  completefn=self._complete2D,
+                                  update_chisqr=update_chisqr,
+                                  exception_handler=self._calc_exception,
+                                  source=source)
             self.calc_2D.queue()
         except:
@@ -1926,4 +1931,5 @@
                                   #updatefn = self._update1D,
                                   update_chisqr=update_chisqr,
+                                  exception_handler=self._calc_exception,
                                   source=source)
             self.calc_1D.queue()
Index: src/sas/sasgui/perspectives/fitting/model_thread.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/model_thread.py	(revision d85c194ea2f78cb2b9b3de9c969e1b8ebea6b6d2)
+++ src/sas/sasgui/perspectives/fitting/model_thread.py	(revision 934ce6493af6e904cf20f2500ef522b42192adfd)
@@ -25,7 +25,9 @@
                  source='model',
                  yieldtime=0.04,
-                 worktime=0.04
+                 worktime=0.04,
+                 exception_handler=None,
                  ):
-        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime)
+        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime,
+                            exception_handler=exception_handler)
         self.qmin = qmin
         self.qmax = qmax
@@ -133,12 +135,11 @@
                  updatefn=None,
                  yieldtime=0.01,
-                 worktime=0.01
+                 worktime=0.01,
+                 exception_handler=None,
                  ):
         """
         """
-        CalcThread.__init__(self, completefn,
-                 updatefn,
-                 yieldtime,
-                 worktime)
+        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime,
+                            exception_handler=exception_handler)
         self.fid = fid
         self.data = data
