我正在Linux上使用64位8.4.3 Tcl非线程,并且遇到了奇怪的行为。
我的C ++应用程序具有一个计时器,该计时器使用XtAppProcessEvent
执行某些Xt处理程序。其中一个处理程序调用{{1}}。
我有一个Tcl脚本,可以打开一个空管道并将fileevent附加到打开的通道。
Tcl_DoOneEvent
这可以多次完成。频道名称为set jobId [open "| "]
fileevent $jobId readable
后,工具会挂起。使用Tcl库的调试版本。它显示执行以下部分后,readyMasks [0]始终为0:
file35
输入检查掩码为72(1001000)。
这是奇怪的部分:
当我到达工具挂起的位置时,如果我打开一个新的外壳选项卡,该工具将不再挂起并继续按预期执行。当打开新的外壳程序选项卡时,// tclUnixNotfy.c:772
numFound = select(tsdPtr->numFdBits,
(SELECT_MASK *) &tsdPtr->readyMasks[0],
(SELECT_MASK *) &tsdPtr->readyMasks[MASK_SIZE],
(SELECT_MASK *) &tsdPtr->readyMasks[2*MASK_SIZE], timeoutPtr);
变为72。
该工具在32位时正常运行。我不知道64位是怎么回事。
我已经在Redhat 5、6和7上进行了尝试,没有任何区别。
答案 0 :(得分:1)
所以,我找出了问题所在。
该问题基本上是由于移入integer
而不是long
引起的。在Tcl中,此操作在tclUnixChan.c
中完成,同时计算索引和要在tsdPtr->checkMasks
中对其进行修改的位:
index = fd/(NBBY*sizeof(fd_mask));
bit = 1 << (fd%(NBBY*sizeof(fd_mask)));
位线必须为1L <<
,而不是1 <<
。 fd_mask
本身是long
,并在sys/types.h
中定义。这只是问题的一部分。
sys/types.h
还具有设置或清除fd_masks中的位(FD_CLR
,FD_SET
,FD_ISSET
,FD_ZERO
)时应使用的宏的定义。
此问题在版本8.4.9
中已部分修复,在版本8.4.20
中已完全修复。
此修复是通过使用types.h
中定义的宏完成的,而不是手动操作fd_mask
位。
版本8.4.9
中引入的部分修补程序位于tclUnixNotfy.c
中:
SelectMasks
,该结构使用fd_set
中定义的types.h
类型checkMasks
和readyMasks
字段从fd_mask
数组更改为SelectMasks
index
,bit
,Tcl_CreateFileHandler
,Tcl_DeleteFileHandler
中用于处理掩码的Tcl_WaitForEvent
和NotifierThreadProc
变量已被删除,{{ 1}},FD_CLR
,FD_SET
,FD_ISSET
代替。FD_ZERO
将Tcl_WaitForEvent
分配给readyMasks
,而不是在调用checkMasks
之前使用memcpy
select
铸造为readyMasks
的过程,并且现在直接在类型SELECT_MASK *
的{{1}}结构元素上使用了&
运算符。 版本SelectMasks
中引入的修补程序的另一部分位于fd_set
中:
8.4.20
中用于处理掩码的tclUnixChan.c
和index
变量,并分别删除了bit
,TclUnixWaitForFile
,FD_CLR
,{{ 1}}代替了。FD_SET
类型而不是在FD_ISSET
中创建FD_ZERO
数组。fd_set
的铸造掩码,并且现在直接在创建的fd_mask
变量上使用TclUnixWaitForFile
运算符。在SELECT_MASK *
和&
中所做的更改的指导下,我修补了当前版本的fd_set
,因为我没有灵活性来升级整个8.4.3
版本
关于为什么打开一个新的外壳窗口的理论使该工具能够正常工作:
由于移入错误大小的容器并使用8.4.9
的长度为8.4.20
的奇怪Tcl
导致的内存损坏,我最终指向的memcpy
与窗口管理有关因此,为什么打开一个新的shell会选择返回非零值,原因是我指向的这些错误3*MASK_SIZE
通道上有数据。
使我引向该理论的是fd
输出和fd
输出:
strace
挂起时的输出重复以下部分:
lsof
当我打开一个新的shell标签时, strace
的输出更改为:
poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 2, 0) = 0 (Timeout)
recvfrom(4, 0x80e21f4, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(4, 0x80e21f4, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 2, 0) = 0 (Timeout)
recvfrom(6, 0x8380d64, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
select(36, [3 6], [], [], {0, 0}) = 0 (Timeout)
recvfrom(6, 0x8380d64, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(6, 0x8380d64, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
select(36, [3 6], [], [], {0, 0}) = 0 (Timeout)
recvfrom(6, 0x8380d64, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 2, 0) = 0 (Timeout)
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x4c3cd70, [CHLD], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x37eec0f790}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
strace
输出显示了通道poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 2, 0) = 1 ([{fd=4, revents=POLLIN}])
recvfrom(4, "X\1\366\371\264\300\7=\3\0\22\0\10\377\0\0\26\1\26\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 0, NULL, NULL) = 256
recvfrom(4, 0x80e21f4, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(4, 0x80e21f4, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 2, 0) = 0 (Timeout)
recvfrom(6, "X\1\321/\264\300\7=\3\0\22\0\10\377\0\0\26\1\26\1\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 0, NULL, NULL) = 256
recvfrom(6, 0x8380d64, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
select(36, [3 6], [], [], {0, 0}) = 1 (in [3], left {0, 0})
recvfrom(6, 0x8380d64, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
read(35, "", 4096) = 0
close(35) = 0
和lsof
的以下内容:
4
频道6
和myexec 13626 aymansalah 4u IPv4 1607796326 0t0 TCP rhe6x64:38787->nx-svr:7016 (ESTABLISHED)
myexec 13626 aymansalah 6u IPv4 1607837231 0t0 TCP rhe6x64:38788->nx-svr:7016 (ESTABLISHED)
是将机器连接到NX服务器的频道。
参考文献: