问题记录:
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钩子退出。
相关推荐
总结来说,处理子进程退出的关键在于理解进程间通信机制,尤其是信号和`waitpid`函数的使用。在编写多进程程序时,正确处理子进程的生命周期能确保系统的稳定性和数据一致性。同时,这也是系统级编程中不可或缺的...
### vb/vba引用excel无法退出excel进程的解决方法 在使用VB/VBA编程语言操作Excel时,经常会遇到一个令人头疼的问题:尽管已经执行了`xlapp.Quit` 和 `Set xlapp = Nothing`来关闭Excel应用并释放相关资源,但Excel...
总结来说,`exit()`是最常用的进程退出方式,因为它提供了完整的清理功能;`_exit()`则用于避免清理过程,适用于特殊需求;而主函数中的`return`则是一种简洁的退出方式,适用于简单的程序结构。在编写程序时,根据...
- 调用`fork()`创建子进程,并让父进程退出。 - 子进程中调用`setsid()`创建新的会话,脱离原有终端。 - 改变当前工作目录为根目录。 - 设置文件权限掩码为0,以便进程可以自由地创建文件。 - 关闭所有不必要的...
在这个总结中,我们将深入探讨进程的性质、编程技巧以及进程的退出机制,这些都是初学者在学习多任务处理时必须掌握的基础知识。 首先,我们要理解什么是进程。进程是计算机中运行的程序的一个实例,它包括程序代码...
本文将深入探讨进程的创建、进程退出以及注册表操作的相关知识。 首先,我们来看进程的创建。在Windows API中,`CreateProcess`函数是用于创建新进程的主要方法。这个函数接收多个参数,包括要执行的应用程序名称、...
原来的方法是不释放资源的,使得程序退出后资源无法释放。我们改进了方法,在程序退出时销毁共享内存和信号量集,从而释放资源。 三、对软件开发的基本流程的了解 通过完成这个项目,我对软件开发的基本流程有了...
需要注意的是,进程退出时,与其挂接的共享内存不会自动删除,需要手动调用`shmdt()`来卸载。此外,当父进程创建了共享内存,子进程会继承这些共享内存。如果共享内存被标记为删除,且挂接数为0,内核会自动清理这个...
总结起来,"pb9.0 pb11.5 强制结束进程 可支持多个同名进程强杀"涉及到的是Progress OpenEdge环境下,如何在不同版本中高效且安全地结束同名进程的技巧和策略,包括使用工具、编写脚本以及了解版本差异等。...
### 解决U盘无法正常退出的方法 在使用Windows XP系统的过程中,用户经常会遇到U盘无法正常退出的问题。当试图安全删除U盘时,系统可能会弹出提示“现在无法停止‘通用卷’设备,请稍候再停止该设备”。这不仅让人...
总结来说,VC++开发中,进程操作是系统编程的重要部分,涉及到枚举系统中运行的进程、关闭指定进程以及使用进程ID进行各种操作。通过学习和熟练掌握这些技术,开发者可以更好地控制和管理应用程序与其他进程的交互。...
这个函数需要进程句柄和退出码。以下是C++中使用`TerminateProcess`的示例: ```cpp #include BOOL terminateProcess(HANDLE processHandle, DWORD exitCode) { return TerminateProcess(processHandle, exit...
`wait()`会阻塞父进程,直到任何子进程终止,返回子进程的退出状态。`waitpid()`更灵活,允许指定要等待的特定子进程ID,并且可以设置等待选项。 最后,孤儿进程和守护进程是两种特殊类型的进程。孤儿进程是其父...
当有进程退出临界区时,管理进程检查队列中的下一个进程,并允许其进入临界区。 #### 3. 访问准则 - **空闲让进**:如果临界区为空闲状态,则任何进程都可以进入。 - **忙则等待**:如果有进程正在临界区内,则...
# 第一次fork,创建子进程,父进程退出 pid = os.fork() if pid > 0: sys.exit(0) # 父进程退出 except OSError as e: sys.stderr.write(f"fork failed: {e}\n") sys.exit(1) # 终端分离,改变工作目录,...
- `exit()`和 `_exit()`用于进程退出,但`exit()`会执行清理工作,如执行析构函数和释放文件描述符。 - `wait()`和`waitpid()`函数用于父进程等待子进程结束,回收子进程资源。 8. **进程控制函数`exec()`系列**...
在本场景中,"进程监视器"是一款工具,它能够监控特定的进程,一旦发现该进程失去响应或者意外退出,它会自动重启这个进程,并且能模拟用户操作,比如点击指定的按钮或输入特定的文本,以确保进程能够完整启动。...
总结来说,VB提供的`Process`类使得开发者能够轻松地进行进程管理,包括查找、监控和结束进程。"vb写的结束指定进程"这个程序就是一个很好的实践案例,展示了如何利用这些功能实现实用的进程管理工具。在编程时,...
3. **退出进程**:函数让当前进程退出,关闭所有文件,取消对节点的引用,唤醒父进程,并将子进程的父进程更改为初始进程。进程状态变为"已退出",调度程序会处理进程的退出。 4. **等待子进程**:函数用于父进程...
总结一下,当我们遇到任务管理器无法结束的进程时,可以尝试使用ntsd命令。创建批处理文件可以简化这一操作,但需谨慎对待,避免对系统造成负面影响。通过深入理解这些工具和命令,我们可以更有效地管理和维护我们的...