首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

过程无法退出总结

2013-10-31 
进程无法退出总结问题记录:jython 运行某个脚本不会退出,通过jstack发现主线程等在Thread.join()上:MainT

进程无法退出总结

问题记录:
jython 运行某个脚本不会退出,通过jstack发现主线程等在Thread.join()上:

"MainThread" prio=10 tid=0x000000005891a000 nid=0x7d6d in Object.wait() [0x0000000041f5d000]
?? java.lang.Thread.State: WAITING (on object monitor)
??? at java.lang.Object.wait(Native Method)
??? - waiting on <0x00000000f7c50b18> (a org.python.core.FunctionThread)
??? at java.lang.Thread.join(Thread.java:1186)
??? - locked <0x00000000f7c50b18> (a org.python.core.FunctionThread)
??? at java.lang.Thread.join(Thread.java:1239)
??? at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
??? at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
??? at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
??? at java.lang.reflect.Method.invoke(Method.java:597)
??? at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:186)
??? at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:204)
??? at org.python.core.PyObject.__call__(PyObject.java:403)
??? at org.python.core.PyObject.__call__(PyObject.java:407)
??? at org.python.core.PyMethod.__call__(PyMethod.java:121)
??? at threading$py.join$22(/duitang/dist/sys/jython/Lib/threading.py:126)
??? at threading$py.call_function(/duitang/dist/sys/jython/Lib/threading.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:301)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:127)
??? at org.python.core.PyFunction.__call__(PyFunction.java:347)
??? at org.python.core.PyMethod.__call__(PyMethod.java:121)
??? at threading$py._MainThread__exitfunc$40(/duitang/dist/sys/jython/Lib/threading.py:252)
??? at threading$py.call_function(/duitang/dist/sys/jython/Lib/threading.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:301)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:194)
??? at org.python.core.PyFunction.__call__(PyFunction.java:417)
??? at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:232)
??? at org.python.core.PyMethod.__call__(PyMethod.java:223)
??? at org.python.core.PyMethod.__call__(PyMethod.java:218)
??? at org.python.core.PyObject._callextra(PyObject.java:543)
??? at atexit$py._run_exitfuncs$1(/duitang/dist/sys/jython/Lib/atexit.py:34)
??? at atexit$py.call_function(/duitang/dist/sys/jython/Lib/atexit.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:120)
??? at org.python.core.PyFunction.__call__(PyFunction.java:337)
??? at org.python.core.PyFunction.__call__(PyFunction.java:332)
??? at org.python.core.PySystemState.callExitFunc(PySystemState.java:555)
??? at org.python.util.PythonInterpreter.cleanup(PythonInterpreter.java:344)
??? at org.python.util.jython.run(jython.java:383)
??? at org.python.util.jython.main(jython.java:137)

查看thread代码发现,进程退出的时候会通过atexit触发__exitfunc,内部实现就是等待所有非Daemon执行完毕。

class _MainThread(Thread):    def __init__(self):        Thread.__init__(self, name="MainThread")        import atexit        atexit.register(self.__exitfunc)    def _create_thread(self):        return java.lang.Thread.currentThread()    def _set_daemon(self):        return False    def __exitfunc(self):        _unregister_thread(self._thread)        t = _pickSomeNonDaemonThread()        while t:            t.join()            t = _pickSomeNonDaemonThread()

?
通过代码定位发现是stomp启动时会启动一个线程开启read_loop,代码如下:

def start(self):    """    Start the connection. This should be called after all    listeners have been registered. If this method is not called,    no frames will be received by the connection.    """    self.__running = True    self.__attempt_connection()    thread = self.create_thread_fc(self.__receiver_loop)    self.__notify('connecting')

通过jstack也可以看到:
"Thread-1" prio=10 tid=0x00000000589e8800 nid=0x7d8f runnable [0x0000000041638000]
?? java.lang.Thread.State: RUNNABLE
??? at sun.nio.ch.FileDispatcher.read0(Native Method)
??? at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:21)
??? at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:198)
??? at sun.nio.ch.IOUtil.read(IOUtil.java:171)
??? at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:243)
??? - locked <0x00000000f7c43b30> (a java.lang.Object)
??? at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
??? at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
??? at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
??? at java.lang.reflect.Method.invoke(Method.java:597)
??? at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:186)
??? at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:204)
??? at org.python.core.PyObject.__call__(PyObject.java:420)
??? at org.python.core.PyObject.__call__(PyObject.java:424)
??? at org.python.core.PyMethod.__call__(PyMethod.java:136)
??? at socket$py._do_read_nio$49(/duitang/dist/sys/jython/Lib/socket.py:471)
??? at socket$py.call_function(/duitang/dist/sys/jython/Lib/socket.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:149)
??? at org.python.core.PyFunction.__call__(PyFunction.java:357)
??? at org.python.core.PyMethod.__call__(PyMethod.java:136)
??? at socket$py.read$52(/duitang/dist/sys/jython/Lib/socket.py:486)
??? at socket$py.call_function(/duitang/dist/sys/jython/Lib/socket.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:149)
??? at org.python.core.PyFunction.__call__(PyFunction.java:357)
??? at org.python.core.PyMethod.__call__(PyMethod.java:136)
??? at socket$py.recv$153(/duitang/dist/sys/jython/Lib/socket.py:1327)
??? at socket$py.call_function(/duitang/dist/sys/jython/Lib/socket.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:301)
??? at org.python.core.PyFunction.function___call__(PyFunction.java:406)
??? at org.python.core.PyFunction.__call__(PyFunction.java:401)
??? at org.python.core.PyFunction.__call__(PyFunction.java:396)
??? at org.python.core.PyObject._callextra(PyObject.java:543)
??? at socket$py.map_exception$27(/duitang/dist/sys/jython/Lib/socket.py:171)
??? at socket$py.call_function(/duitang/dist/sys/jython/Lib/socket.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:301)
??? at org.python.core.PyFunction.function___call__(PyFunction.java:406)
??? at org.python.core.PyFunction.__call__(PyFunction.java:401)
??? at org.python.core.PyFunction.__call__(PyFunction.java:396)
??? at org.python.core.PyObject._callextra(PyObject.java:543)
??? at socket$py.set_last_error$29(/duitang/dist/sys/jython/Lib/socket.py:183)
??? at socket$py.call_function(/duitang/dist/sys/jython/Lib/socket.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:301)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:141)
??? at org.python.core.PyFunction.__call__(PyFunction.java:357)
??? at org.python.core.PyMethod.__call__(PyMethod.java:136)
??? at stomp.connect$py._Connection__read$30(/duitang/dist/app/main/java/japa/src/main/webapp/stomp/connect.py:851)
??? at stomp.connect$py.call_function(/duitang/dist/app/main/java/japa/src/main/webapp/stomp/connect.py)
??? at org.python.core.PyTableCode.call(PyTableCode.java:165)
??? at org.python.core.PyBaseCode.call(PyBaseCode.java:134)
??? at org.python.core.PyFunction.__call__(PyFunction.java:347)
??? at org.python.core.PyMethod.__call__(PyMethod.java:121)
??? at stomp.connect$py._Connection__receiver_loop$28(/duitang/dist/app/main/java/japa/src/main/webapp/stomp/connect.py:756)
??? at stomp.connect$py.call_function(/duitang/dist/app/main/java/japa/src/main/webapp/stomp/connect.py)

改进措施:
mqclient新增一个atexit.register(mqclient.stop)

总结:
1. 后台线程需要管理好自己的生命周期,提供stop接口
2. 线程应该daemon还是非daemon需要考虑一下,一般不可打断的线程应该设计为非daemon的,通过exit钩子退出。

?

热点排行