简体   繁体   中英

Throwing exceptions: Node.js vs Gevent

Someone at a meetup yesterday told me that if a callback throws an exception in Node.js, it will crash the entire process. But if a greenlet throws an uncaught exception in Gevent, it only crashes the greenlet.

I don't have experience with Gevent, and am wondering if that is true.

Here is an exmaple code that shows that when a greenlet throws an uncaught excpetion, the whole process won't be crashed. The code is here and the output is as following:

Traceback (most recent call last):  
File "/usr/lib/python2.7/site-packages/gevent/greenlet.py", line 327, in run  
  result = self._run(*self.args, **self.kwargs)  
File "test_exception_greenlet.py", line 31, in _fail  
  raise Exception('you fail')  
Exception: you fail  
<Greenlet at 0x8b5cc5c: <bound method TestgException._fail of <__main__.TestgException object at 0x8bd4a0c>>> failed with Exception  

win ready? True    
fail ready? True  
win successful()? True  
fail successful()? False  
exception: Exception('you fail',)  

When using gevent to implemenet concurrency tasks, you should generate some coroutines , namely greenlets , and then the main thread should switch to a special greenlet named hub and then the loop happens among greenlets . The workflow is like this:

main thread -> one greenlet -> hub greenlet -> a greenlet -> hub greenlet -> a greenlet -> ... -> some greenlet -> main thread -> ... (maybe enters the loop again)

From here, you should know how a greenlet runs internally. A greenlet is an instance of Greenlet . When a greenlet runs, it invokes its run() method. Here is the source code of run() in Greenlet class:

def run(self):
    try:
        if self._start_event is None:
            self._start_event = _dummy_event
        else:
            self._start_event.stop()
        try:
            result = self._run(*self.args, **self.kwargs)
        except:
            self._report_error(sys.exc_info())
            return
        self._report_result(result)
    finally:
        self.__dict__.pop('_run', None)
        self.__dict__.pop('args', None)
        self.__dict__.pop('kwargs', None)

The _run() method here is a binding with a task you want to run as a greenlet. From here you could see that if an exception happens, it will be caught and reported by _report_error() method. By reading the source code of _report_error() and _report_result() which is invoked by the former, you know that it catches the exception and just the greenlet dies but not the whole process. When a greenlet raises an uncaught exception, it dies and the hub greenlet won't schedule it any more.

If you're insterested in the implementation of Greenlet , here is the source code

Do Node.js apps crash upon uncaught exception? Yes. See, eg, http://shapeshed.com/uncaught-exceptions-in-node/

Do uncaught exceptions in Gevent greenlets only bring down the greenlet in question? Yes. See, eg, http://www.gevent.org/gevent.html and in particular Greenlet.exception which "holds the exception instance raised by the function if the greenlet has finished with an error," thus making the exception instance available to the rest of the process, which did not crash.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM