title: Python alarm signals, Time-out the current thread from outside with a handled exception?
body: <p>It is commonly known that <a href="https://stackoverflow.com/questions/44151888/why-only-main-thread-can-set-signal-handler-in-python">signals in python only work inside the main thread</a>, this is my little snippet on this subject:</p>
  
  <pre><code>import signal
  
  from threading import Timer
  from time import sleep
  
  class timeout:
      def __init__(self, seconds=1, error_message='Timeout error'):
          self.seconds = seconds
          self.error_message = error_message
      def handle_timeout(self, signum, frame):
          raise TimeoutError(self.error_message)
      def __enter__(self):
          signal.signal(signal.SIGALRM, self.handle_timeout)
          signal.alarm(self.seconds)
      def __exit__(self, type, value, traceback):
          signal.alarm(0)
  
  def main():
      try:
          with timeout(seconds=2) :
              #do_something
              sleep(3)
              print ("don't come here after 3 seconds")
      except Exception as e:
          print ("catch here",str(e))
      print ("continue ...")
  
  t = Timer(0.0, main)
  t.start()
  </code></pre>
  
  <p>Now, in order to force this to work, i placed <code>signal.signal</code> outside the thread with a hooked dynamic function.</p>
  
  <pre><code>class timeout:
      def __init__(self, seconds=1, error_message='Timeout error'):
          self.seconds = seconds
          self.error_message = error_message
      def handle_timeout(self):
          raise TimeoutError(self.error_message)
      def __enter__(self):
          #fluid.error = self.error_message
          #fluid.__call__ = self.handle_timeout
          signal.alarm(self.seconds)
      def __exit__(self, type, value, traceback):
          signal.alarm(0)
  
  class fluid:
      error = 'Orpheline exception'
      def __init__(self,signum,frame):
              self.signum = signum
              self.frame = frame
      def __call__(self):
          try:
              raise TimeoutError(self.error)
          except Exception as e:
              print ("catch now", str(e))
  
  signal.signal(signal.SIGALRM, lambda x,y:fluid(x,y)())
  
  t = Timer(0.0, main)
  
  try:
      t.start()
  except Exception as e:
      print ("catch there",str(e))
  </code></pre>
  
  <p>Dabbling with this issue using monkey patching yields the folowing:</p>
  
  <ul>
  <li>In case i uncomment this: <code>fluid.error = self.error_message</code>, the exception is caught inside the class.</li>
  <li>In case i uncomment this: <code>fluid.__call__ = self.handle_timeout</code>, the exception is neither caught in both main handlers, the program exits!</li>
  </ul>
  
  <p>The only solution that worked for me is furnishing a new flag-value called <code>skipvalue</code> to check if there is an exception or not in this parallel thread:</p>
  
  <pre><code>class timeout:
      def __init__(self, seconds=1, error_message='Timeout error'):
          self.seconds = seconds
          self.error_message = error_message
          self.skipvalue = False
          self.SKIP = lambda : self.skipvalue
      def handle_timeout(self):
          raise TimeoutError(self.error_message)
      def timeitout(self):
          #print('not caught ',self.error_message)
          self.skipvalue = True
      def __enter__(self):
          fluid.error = self.error_message
          #fluid.__call__ = self.handle_timeout
          fluid.__call__ = self.timeitout
          signal.alarm(self.seconds)
          return self.SKIP
      def __exit__(self, type, value, traceback):
          signal.alarm(0)
  
  def main():
      try:
          with timeout(seconds=2,error_message="Some message") as e :
              #do_something
              sleep(3)
              if e():
                  raise Timeout(fluid.error)
              print ("don't come here after 3 seconds")
      except Exception as e:
          print ("catch here",str(e))
      print ("continue ...")
  
  t = Timer(0.0, main)
  t.start()
  </code></pre>
  
  <p>The above takes up to 3 seconds with sleep function, with an arbitrary loop I need to check around the new value at each execution cycle.</p>
  
  <hr>
  
  <p><strong>My Question</strong>:</p>
  
  <ul>
  <li>Is there some way more elegant and built-in to work this aim witout stuffing the code with unnecessary variables or classes or forking child-processes?</li>
  </ul>