Tcl fileevent挂在64位版本的Tcl

时间:2019-06-02 16:23:11

标签: c++ linux tcl 64-bit x11

我正在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上进行了尝试,没有任何区别。

1 个答案:

答案 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_CLRFD_SETFD_ISSETFD_ZERO)时应使用的宏的定义。

此问题在版本8.4.9中已部分修复,在版本8.4.20中已完全修复。

此修复是通过使用types.h中定义的宏完成的,而不是手动操作fd_mask位。

版本8.4.9中引入的部分修补程序位于tclUnixNotfy.c中:

    创建了
  1. 结构SelectMasks,该结构使用fd_set中定义的types.h类型
  2. ThreadSpecificData checkMasksreadyMasks字段从fd_mask数组更改为SelectMasks
  3. indexbitTcl_CreateFileHandlerTcl_DeleteFileHandler中用于处理掩码的
  4. Tcl_WaitForEventNotifierThreadProc变量已被删除,{{ 1}},FD_CLRFD_SETFD_ISSET代替。
  5. FD_ZEROTcl_WaitForEvent分配给readyMasks,而不是在调用checkMasks之前使用memcpy
  6. 现在取消了在调用select时将select铸造为readyMasks的过程,并且现在直接在类型SELECT_MASK *的{​​{1}}结构元素上使用了&运算符。

版本SelectMasks中引入的修补程序的另一部分位于fd_set中:

    删除了8.4.20中用于处理掩码的
  1. tclUnixChan.cindex变量,并分别删除了bitTclUnixWaitForFileFD_CLR,{{ 1}}代替了。
  2. 使用
  3. FD_SET类型而不是在FD_ISSET中创建FD_ZERO数组。
  4. 现在取消了在调用select时向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

频道6myexec 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服务器的频道。


参考文献: