- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
考虑这个小的 python 脚本 odd-read-blocking.py
:
#!/usr/bin/python
import signal
import sys
sig = None
def handler(signum, frame):
global sig
sig = signum
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
x = sys.stdin.read(3)
print 'signal', sig
print 'read bytes', len(x)
exit(0)
我运行它并向它提供两个字节的标准输入数据 ('a' + '\n'):
> echo a | ./odd-read-blocking.py
signal None
read bytes 2
>
很好。
现在我用相同的两个字节输入它(通过在其标准输入中键入 'a' + '\n')。请注意,标准输入还没有到达 EOF,并且可能会有更多数据到来。所以读取 block ,因为它期望多一个字节。我在脚本上使用 Ctrl+C。
> ./odd-read-blocking.py
a
^Csignal 2
read bytes 2
>
很好。我们看到已经读取了两个字节并收到了信号 2。
现在我打开一个标准输入流,但不向其发送任何字节。读取 block 如预期。如果我现在在脚本上使用 Ctrl+C,它会一直坐在那里等待。读取不会中断。 SIGINT 将不会被处理。
> ./odd-read-blocking.py
^C
这里什么都没有。脚本仍在运行(在读取时似乎被阻止)。
现在按回车一次,然后再次按 Ctrl+C:
^Csignal 2
read bytes 1
>
因此,只有在其标准输入上至少接收到一些数据(在本例中为单个“\n”)后,脚本才会按我预期的方式运行并正确中断被阻止的读取并告诉我它已收到信号 2 和读取 1 个字节。
备选方案 1:如上所示,我没有使用 Ctrl+C,而是使用 kill <em>pid</em>
尝试了同样的操作从一个单独的终端。行为相同。
备选方案 2:我没有使用上述的 shell 标准输入,而是这样做了:
> sleep 2000 | ./odd-read-blocking.py
使用 kill <em>pid</em>
时将 SIGTERM 发送到 odd-read-blocking.py
过程我得到相同的行为。这里,脚本进程只能使用SIGKILL(9)来杀死。
为什么读取在一个尚未空但仍处于事件状态的标准输入流上阻塞时没有被中断?
我觉得这很奇怪。谁没有?谁能解释一下?
最佳答案
如果 Python 信号处理程序抛出异常以放弃正在进行的 file.read
,则任何已读取的数据都会丢失。 (任何异步异常,比如默认的 KeyboardInterrupt
,基本上不可能阻止这种故障,除非你有一个 way to mask it。)
为了尽量减少对此的需求,file.read
在被信号中断时提前返回(即,字符串比请求的更短)——注意这除了记录的 EOF 和非阻塞 I/O 案例之外!但是,当它还没有数据时它不能这样做,因为它返回空字符串以指示 EOF。
一如既往,理解这种行为的方法是使用 strace
。
当信号到达而进程被阻塞时,实际的 read
系统调用会进退两难。首先,调用 (C) 信号处理程序——但由于这可能发生在任何两条指令之间,因此除了设置标志(或写入自管道)之外,它几乎无能为力。然后呢?如果设置了SA_RESTART
,则恢复通话;否则……
如果尚未传输任何数据,read
可能会失败,客户端可以检查其信号标志。它无法通过特殊的 EINTR
来澄清 I/O 实际上没有任何问题。
如果一些数据已经写入(用户空间)缓冲区,它不能只返回“失败”,因为数据会丢失——客户端无法知道缓冲区中有多少(如果有的话)数据.所以它只返回成功(到目前为止读取的字节数)!像这样的短读取总是有可能的:客户端必须再次调用 read
以检查它是否已到达文件末尾。 (就像 file.read
一样,0 字节的短读取将 EOF。)因此,客户端必须在每次读取后检查其信号标志,无论是否成功. (请注意,这仍然不是 perfectly reliable ,但对于许多交互式用例来说已经足够了。)
系统调用并不是全部:毕竟,终端的正常配置让它在看到换行符后立即返回。 Python 2 的低级 file.read
是一个 wrapper for fread
, 如果一个很短,它将发出另一个 read
。但是当读取失败并显示 EINTR
时,fread
会提前返回并且 file.read
会调用您的 (Python) 信号处理程序。 (如果你向它添加输出,你会看到它会立即为你发送的每个信号调用,即使 file.read
没有返回。)
然后它面临着与系统调用类似的困境:正如所讨论的,短读不能为空,因为它意味着 EOF。然而,与 C 信号处理程序不同的是,Python 信号处理程序可以执行任意工作(包括引发异常以立即中止 I/O,如开头所述,代价是冒着数据丢失的风险),并且它被认为是对接口(interface)隐藏可能性 EINTR
。所以 fread
调用只是默默地重复。
重试规则changed in 3.5 .现在,即使手头有数据,io.IOBase.read
也会恢复;这更一致,但它 forces使用异常来停止读取,这意味着您不能选择等待某些数据以免丢失您已经拥有的任何数据。非常重量级的解决方案是切换到多路复用 I/O 并使用 signal.set_wakeup_fd()
;这具有允许 SIGINT 影响主线程的额外优势,而不必费心在所有其他线程中屏蔽它。
关于python - 在具有自定义信号处理程序的情况下在 python 2 中读取 sys.stdin 时出现奇怪的阻塞行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49653837/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!