Итак, я разобрался в проблеме.
Проблема в основном из-за смещения 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
:
- struct
SelectMasks
было создано с использованием типа fd_set
, которыйопределяется в полях types.h
- ThreadSpecificData
checkMasks
и readyMasks
, измененных из массивов fd_mask
на значения SelectMasks
index
и bit
, используемые в Tcl_CreateFileHandler
, Tcl_DeleteFileHandler
, Tcl_WaitForEvent
, NotifierThreadProc
для работы с масками были удалены и вместо них были использованы FD_CLR
, FD_SET
, FD_ISSET
, FD_ZERO
. Tcl_WaitForEvent
присваивает readyMasks
checkMasks
вместо использования memcpy
перед вызовом select
- Приведение
readyMasks
к SELECT_MASK *
при вызове select теперь удаленоОператор nd &
теперь используется непосредственно для элементов структуры SelectMasks
типа fd_set
.
Другая часть исправления, представленная в версии 8.4.20
, была в tclUnixChan.c
: *Переменные 1077 *
index
и bit
, используемые в TclUnixWaitForFile
для работы с масками, были удалены и вместо них использовались FD_CLR
, FD_SET
, FD_ISSET
, FD_ZERO
. fd_set
тип использовался вместо создания fd_mask
массивов в TclUnixWaitForFile
. - Приведение масок к
SELECT_MASK *
при вызове select теперь удалено, а оператор &
теперь используется всоздал fd_set
переменных напрямую.
Я исправил свою текущую версию 8.4.3
, руководствуясь изменениями, сделанными в 8.4.9
и 8.4.20
, потому что у меня нет гибкости в обновлениицелая Tcl
версия.
Моя теория о том, почему открытие нового окна оболочки заставило инструмент работать:
Из-за повреждения памяти, вызванного перемещением в неправильный контейнерразмер и использование memcpy
со странной длиной 3*MASK_SIZE
, fd
, на который я в конечном итоге указалТаким образом, управление indow связано с тем, почему при открытии новой оболочки было выбрано возвращение ненулевого значения из-за наличия данных о тех неправильных fd
каналах, на которые я указываю.
Что привело меня к этой теории, так это вывод strace
а также вывод lsof
: вывод
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)
Каналы 4
и 6
- это каналы, соединяющие мою машину сСервер NX.
Ссылки: