title: Exception in thread Thread-4 - finding the reason or catch the exception
body: <p>I'm running this script on my server in order to send push notifications on new mail arrival. It works great but sometimes the script will crash with the error below. I don't know why it's crashing and I can't reproduce it on my own. When it fails it won't go into the except section. 
  I've tried: <code>except self.abort:</code> <code>except M.abort:</code> <code>except M.error:</code> </p>
  
  <ol>
  <li><p>Any idea why it's crashing?</p></li>
  <li><p>Is it possible, for a short term solution,  to kill all the threads and restart the script from the <code>except</code> section?</p></li>
  </ol>
  
  <p>.......</p>
  
  <pre><code>import socket, ssl, json, struct, re
  import imaplib2, time
  from threading import *
  
  # enter gmail login details here
  USER="YOUR.NAME@gmail.com"
  PASSWORD="YOUR-GMAIL-PASSWORD"
  # enter device token here
  deviceToken = 'XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX '
  deviceToken = deviceToken.replace(' ','').decode('hex')
  currentBadgeNum = -1
  
  def getUnseen():
      (resp, data) = M.status("INBOX", '(UNSEEN)')
      print data
      return int(re.findall("UNSEEN (\d)*\)", data[0])[0])    
  
  def sendPushNotification(badgeNum):
      global currentBadgeNum, deviceToken
      if badgeNum != currentBadgeNum:
          currentBadgeNum = badgeNum
          thePayLoad = {
               'aps': {
          #          'alert':'Hello world!',
                    'sound':'',
                    'badge': badgeNum,
                    },
               'test_data': { 'foo': 'bar' },
               }
          theCertfile = 'certfile.pem'
          theHost = ('gateway.sandbox.push.apple.com', 2195)
  
          data = json.dumps(thePayLoad)
          theFormat = '!BH32sH%ds' % len(data)
          theNotification = struct.pack(theFormat, 0, 32, deviceToken, len(data), data)
  
          ssl_sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), certfile=theCertfile)
          ssl_sock.connect(theHost)
          ssl_sock.write(theNotification)
          ssl_sock.close()
          print "Sent Push alert."
  
  # This is the threading object that does all the waiting on 
  # the event
  class Idler(object):
      def __init__(self, conn):
          self.thread = Thread(target=self.idle)
          self.M = conn
          self.event = Event()
  
      def start(self):
          self.thread.start()
  
      def stop(self):
          # This is a neat trick to make thread end. Took me a 
          # while to figure that one out!
          self.event.set()
  
      def join(self):
          self.thread.join()
  
      def idle(self):
          # Starting an unending loop here
          while True:
              # This is part of the trick to make the loop stop 
              # when the stop() command is given
              if self.event.isSet():
                  return
              self.needsync = False
              # A callback method that gets called when a new 
              # email arrives. Very basic, but that's good.
              def callback(args):
                  if not self.event.isSet():
                      self.needsync = True
                      self.event.set()
              # Do the actual idle call. This returns immediately, 
              # since it's asynchronous.
              self.M.idle(callback=callback)
              # This waits until the event is set. The event is 
              # set by the callback, when the server 'answers' 
              # the idle call and the callback function gets 
              # called.
              self.event.wait()
              # Because the function sets the needsync variable,
              # this helps escape the loop without doing 
              # anything if the stop() is called. Kinda neat 
              # solution.
              if self.needsync:
                  self.event.clear()
                  self.dosync()
  
      # The method that gets called when a new email arrives. 
      def dosync(self):
          print "Got an event!"
          numUnseen = getUnseen()
          sendPushNotification(numUnseen)
  
  try:
      # Set the following two lines to your creds and server
      print 'starting'
      global M
      M = imaplib2.IMAP4_SSL("imap.gmail.com")
      M.login(USER, PASSWORD)
      # We need to get out of the AUTH state, so we just select 
      # the INBOX.
      #M.list()
      M.select('INBOX', readonly=True)
      numUnseen = getUnseen()
      getText()
      #print M.status("INBOX", '(UNSEEN)')
      # Start the Idler thread
      sendPushNotification(numUnseen)
      idler = Idler(M)
      idler.start()
      # Sleep forever, one minute at a time
      while True:
          time.sleep(60)
  
  except self.abort:
      print 'we had a problem, dont worry! Ill fix it!'
      idler = Idler(M)
  finally:
      # Clean up.
      idler.stop()
      idler.join()
      M.close()
      # This is important!
      M.logout()
  </code></pre>
  
  <p>.....................</p>
  
  <p>.....................</p>
  
  <pre><code>  17:35.99 imap.gmail.com reader last 20 log messages:
    17:36.02 imap.gmail.com handler last 20 log messages:
  Got an event!
  Exception in thread Thread-4:
  Traceback (most recent call last):
    File "/usr/local/lib/python2.7/threading.py", line 551, in __bootstrap_inner
      self.run()
    File "/usr/local/lib/python2.7/threading.py", line 504, in run
      self.__target(*self.__args, **self.__kwargs)
    File "serverx.py", line 229, in idle
      self.dosync()
    File "serverx.py", line 235, in dosync
      numUnseen = getUnseen()
    File "serverx.py", line 150, in getUnseen
      (resp, data) = M.status("INBOX", '(UNSEEN)')
    File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1121, in status
      return self._simple_command(name, mailbox, names, **kw)
    File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1607, in _simple_command
      return self._command_complete(self._command(name, *args), kw)
    File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1305, in _command
      raise self.abort('connection closed')
  abort: connection closed
  </code></pre>