Cygwin: cygtls: fix context alignment

A hang was encountered, apparently triggered by commit 63b503916d,
changing tls_pathbufs from malloc'ed to HeapAlloc'ed memory.  After
lengthy debugging it transpired that adding the heap handle to the
tls_pathbuf struct added 8 bytes to the cygtls area, thus moving
the "context" member by 8 bytes, too, so it was suddently unaligned.

Fix this for now by changing the alignment.

Fix this once and for all, by adding code to the gentls_offsets script
to check if the alignment of the "context" member is 16 bytes.  If not,
print a matching error message, remove the just generated file, and exit
with error.

FIXME: It would be really nice to find a way to auomate the correct
alignment of the "context" member, but I don't see any way to use
alignment attributes to get what we need here.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2022-08-29 15:18:53 +02:00
parent 717c36c0a4
commit dcab768cb9
2 changed files with 14 additions and 2 deletions

View File

@ -178,11 +178,14 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
siginfo_t *sigwait_info; siginfo_t *sigwait_info;
HANDLE signal_arrived; HANDLE signal_arrived;
bool will_wait_for_signal; bool will_wait_for_signal;
#if 0
long __align; /* Needed to align context to 16 byte. */ long __align; /* Needed to align context to 16 byte. */
#endif
/* context MUST be aligned to 16 byte, otherwise RtlCaptureContext fails. /* context MUST be aligned to 16 byte, otherwise RtlCaptureContext fails.
If you prepend cygtls members here, make sure context stays 16 byte If you prepend cygtls members here, make sure context stays 16 byte
aligned. */ aligned. The gentls_offsets script checks for that now and fails
ucontext_t context; if the alignment is wrong. */
ucontext_t __attribute__((__aligned__(__alignof__(long double)))) context;
DWORD thread_id; DWORD thread_id;
siginfo_t infodata; siginfo_t infodata;
struct pthread *tid; struct pthread *tid;

View File

@ -98,3 +98,12 @@ gawk -v start_offset="$start_offset" '\
} }
} }
' ${tmp_file} > "${output_file}" ' ${tmp_file} > "${output_file}"
# Check if the `context' member is 16 bytes aligned. Delete output_file
# and bail out with error if not.
MOD=$(awk '/_cygtls.context_p/{ print $3 % 16; }' "${output_file}")
if [ $MOD -ne 0 ]
then
echo "Error: _cygtls.context member is not 16 bytes aligned!"
rm "${output_file}"
exit 1
fi