我们有一个应用程序,允许用户将任意Tcl代码块(作为回调)传递给自定义API,该API在大型数据树的各个元素上调用它。为了提高性能,这是使用线程池来完成的,所以事情可以被撕掉。
问题是,我们无法控制用户代码,在其中一种情况下,他们正在做一个导致内存爆炸和应用程序崩溃的放置操作。我可以通过将stdout重定向到/dev/null来防止这种情况,这使我相信Tcl的内部缓冲区不能被足够快地清空,所以它一直在缓冲。堆分析似乎证实了这一点。

我不明白的是,我没有弄乱任何stdout的选项,所以它应该是行缓冲,阻塞,4k。所以,我的第一个问题是:为什么会发生这种情况?难道不应该已经施加了反压力来防止这种情况吗?
我的第二个问题是:我如何防止这种情况发生?如果用户想要做一些愚蠢的事情,我更愿意扼杀他们的性能,但我不希望应用程序崩溃。我认为一种解决方案是在调用回调之前重新定义puts来写入文件(或者干脆什么都不做),但我会感兴趣的是,是否有一种方法可以确保通道上的背压,以防止它继续缓冲。
谢谢你的想法!
发布于 2022-01-08 09:38:33
这取决于通道类型和您如何配置它。但是,通常的模型是,写入同步通道(-blocking true)将立即缓冲或写入(根据-buffering选项),并写入异步通道(-blocking false),如果不立即处理,将排队等待内部事件处理程序稍后执行。对于大多数应用程序来说,这都是正确的;听起来好像您已经将异步通道传递给了不调用事件循环(或者至少不是频繁调用)的代码。在启动用户代码之前,尝试将通道设置为同步的;您处于一个单独的线程中,因此阻塞行为对应用程序的其他部分来说不应该是一个问题。
有些频道比较棘手。在Windows等平台上,人们通常会遇到Tk中的控制台通道,在这种情况下,通道最终会写入一个没有最多保留行数的小部件中。
https://stackoverflow.com/questions/70626957
复制相似问题