public inbox for cygwin-developers@cygwin.com
 help / color / mirror / Atom feed
* Fibers and cygtls
@ 2020-09-04 15:13 David McFarland
  2020-09-04 19:51 ` Corinna Vinschen
  2020-09-06 14:19 ` Jon Turney
  0 siblings, 2 replies; 6+ messages in thread
From: David McFarland @ 2020-09-04 15:13 UTC (permalink / raw)
  To: cygwin-developers

For a while now I've been trying to get nix working on Cygwin. It
compiles fine, but when it's run, it will exit unexpectedly in a way
that doesn't return an error code to Cygwin, and doesn't break in gdb.

I tracked this to its use of boost coroutines, which use boost-context
to switch fibers. boost-context can be built using either a custom asm
implementation, or using windows fibers (CreateFiber).

Both the boost-context asm implementation and win32 fibers switch the
NT_TIB StackBase and StackLimit fields (to a user provided buffer) when
switching fibers. StackBase is used to find the cygtls for the current
thread (in _my_tls, and with asm in gendef etc). Because of this, A
program will crash when any syscall is made from a fiber.

I searched for any discussion about this, and couldn't find much.
There's this reference to fibers being broken on Cygwin:

https://schneide.blog/2016/09/19/c-coroutines-on-windows-with-the-fiber-api/

This is a test program which shows the problem using win32 fibers:

===File test.c==============
#include <windows.h>
#include <stdio.h>
#include <unistd.h>

DWORD tls_slot;

#define LOG(x) fprintf(stderr, x " %p %u %u %p %p\n", \
        GetCurrentFiber(), \
        (unsigned)GetCurrentThreadId(), \
        (unsigned)tls_slot, \
        TlsGetValue(tls_slot), \
        NtCurrentTeb());

VOID WINAPI proc(LPVOID parent) {
        LOG("b");
        SwitchToFiber(parent);
}

int main() {
        tls_slot = TlsAlloc();
        TlsSetValue(tls_slot, (void*)0x123);
        LOG("a");
        LPVOID self = ConvertThreadToFiber(0);
        LPVOID fiber = CreateFiber(16 * 1024, &proc, self);
        SwitchToFiber(fiber);
        LOG("c");
        return 0;
}
============================================================

My first idea was to find an unused spot in the TEB to store the cygtls
pointer. This worked, but I couldn't find a field (e.g. user reserved,
or 'spare' bytes), that was safe from being stomped by win32 libs.

The only safe implementation I could think of was to use the win32 TLS
APIs to store the pointer. TlsAlloc is already used in dll_entry to
create a slot for thread entry points. I decided to try reusing that
slot to store the cygtls pointer.

This is my WIP implementation:

===File 0001-Cygwin-store-tls-pointer-in-win32-tls.patch===
From 7a61b556575f03e3e99116dc355aa5999b28c855 Mon Sep 17 00:00:00 2001
From: David McFarland <corngood@gmail.com>
Date: Fri, 4 Sep 2020 10:15:57 -0300
Subject: [PATCH] Cygwin: store tls pointer in win32 tls

---
 winsup/cygwin/cygtls.cc               | 15 +++++++++++++++
 winsup/cygwin/cygtls.h                |  6 +++++-
 winsup/cygwin/dcrt0.cc                |  1 +
 winsup/cygwin/fork.cc                 |  1 +
 winsup/cygwin/gendef                  | 15 ++++++++++-----
 winsup/cygwin/include/cygwin/config.h |  2 +-
 winsup/cygwin/init.cc                 | 12 ++++++++----
 winsup/cygwin/miscfuncs.cc            |  2 ++
 8 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index 1a2213d1f..806f6516f 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -16,6 +16,20 @@ details. */
 #include "sigproc.h"
 #include "exception.h"
 
+extern DWORD cygtls_slot;
+
+void _set_tls(TEB *teb)
+{
+  TlsSetValue(cygtls_slot, teb->Tib.StackBase);
+}
+
+_cygtls* _current_tls()
+{
+  register void *ret;
+  __asm __volatile__ ("movl cygtls_slot(%%rip),%%r10d\nmovq %%gs:0x1480(,%%r10d,8),%0" : "=r" (ret) : : "r10");
+  return (_cygtls *) ((PBYTE) ret - CYGTLS_PADSIZE);
+}
+
 /* Two calls to get the stack right... */
 void
 _cygtls::call (DWORD (*func) (void *, void *), void *arg)
@@ -24,6 +38,7 @@ _cygtls::call (DWORD (*func) (void *, void *), void *arg)
   /* Initialize this thread's ability to respond to things like
      SIGSEGV or SIGFPE. */
   exception protect;
+  _set_tls();
   _my_tls.call2 (func, arg, buf);
 }
 
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index a2e3676fc..c5165818f 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -286,7 +286,11 @@ private:
 #include "cygerrno.h"
 #include "ntdll.h"
 
-#define _my_tls (*((_cygtls *) ((PBYTE) NtCurrentTeb()->Tib.StackBase - CYGTLS_PADSIZE)))
+void _set_tls(TEB*);
+inline void _set_tls() { _set_tls(NtCurrentTeb()); }
+_cygtls* _current_tls();
+
+#define _my_tls (*_current_tls())
 extern _cygtls *_main_tls;
 extern _cygtls *_sig_tls;
 
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 810017956..634404573 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -475,6 +475,7 @@ child_info_fork::alloc_stack ()
 	 StackBase in the child to be the same as in the parent, so that the
 	 computation of _my_tls is correct. */
       teb->Tib.StackBase = (PVOID) stackbase;
+      _set_tls(teb);
     }
 }
 
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 7c07b062e..d5cb0fff3 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -171,6 +171,7 @@ frok::child (volatile char * volatile here)
 		myself->pid, myself->ppid, __builtin_frame_address (0));
   sigproc_printf ("hParent %p, load_dlls %d", hParent, load_dlls);
 
+  _set_tls();
   /* Make sure threadinfo information is properly set up. */
   if (&_my_tls != _main_tls)
     {
diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef
index 431ec67d3..07bf8e200 100755
--- a/winsup/cygwin/gendef
+++ b/winsup/cygwin/gendef
@@ -130,7 +130,8 @@ EOF
 	.seh_proc _sigfe_maybe
 _sigfe_maybe:					# stack is aligned on entry!
 	.seh_endprologue
-	movq	%gs:8,%r10			# location of bottom of stack
+	movl	cygtls_slot(%rip),%r10d
+	movq	%gs:0x1480(,%r10d,8),%r10			# location of bottom of stack
 	leaq	$tls::initialized(%r10),%r11	# where we will be looking
 	cmpq	%r11,%rsp			# stack loc > than tls
 	jge	0f				# yep.  we don't have a tls.
@@ -143,7 +144,8 @@ _sigfe_maybe:					# stack is aligned on entry!
 	.seh_proc _sigfe
 _sigfe:						# stack is aligned on entry!
 	.seh_endprologue
-	movq	%gs:8,%r10			# location of bottom of stack
+	movl	cygtls_slot(%rip),%r10d
+	movq	%gs:0x1480(,%r10d,8),%r10			# location of bottom of stack
 1:	movl	\$1,%r11d			# potential lock value
 	xchgl	%r11d,$tls::stacklock(%r10)	# see if we can grab it
 	movl	%r11d,$tls::spinning(%r10)	# flag if we are waiting for lock
@@ -167,7 +169,8 @@ _sigfe:						# stack is aligned on entry!
 _sigbe:						# return here after cygwin syscall
 						# stack is aligned on entry!
 	.seh_endprologue
-	movq	%gs:8,%r10			# address of bottom of tls
+	movl	cygtls_slot(%rip),%r10d
+	movq	%gs:0x1480(,%r10d,8),%r10			# location of bottom of stack
 1:	movl	\$1,%r11d			# potential lock value
 	xchgl	%r11d,$tls::stacklock(%r10)	# see if we can grab it
 	movl	%r11d,$tls::spinning(%r10)	# flag if we are waiting for lock
@@ -247,7 +250,8 @@ sigdelayed:
 	movdqa	%xmm0,0x20(%rsp)
 	.seh_endprologue
 
-	movq	%gs:8,%r12			# get tls
+	movl	cygtls_slot(%rip),%r12d
+	movq	%gs:0x1480(,%r12d,8),%r12			# location of bottom of stack
 	movl	$tls::saved_errno(%r12),%r15d	# temporarily save saved_errno
 	movq	\$$tls::start_offset,%rcx	# point to beginning of tls block
 	addq	%r12,%rcx			#  and store as first arg to method
@@ -368,7 +372,8 @@ stabilize_sig_stack:
 	subq	\$0x20,%rsp
 	.seh_stackalloc 32
 	.seh_endprologue
-	movq	%gs:8,%r12
+	movl	cygtls_slot(%rip),%r12d
+	movq	%gs:0x1480(,%r12d,8),%r12			# location of bottom of stack
 1:	movl	\$1,%r10d
 	xchgl	%r10d,$tls::stacklock(%r12)
 	movl	%r10d,$tls::spinning(%r12)	# flag if we are waiting for lock
diff --git a/winsup/cygwin/include/cygwin/config.h b/winsup/cygwin/include/cygwin/config.h
index 282637b67..498d6fdc6 100644
--- a/winsup/cygwin/include/cygwin/config.h
+++ b/winsup/cygwin/include/cygwin/config.h
@@ -46,7 +46,7 @@ extern inline struct _reent *__getreent (void)
 {
   register char *ret;
 #ifdef __x86_64__
-  __asm __volatile__ ("movq %%gs:8,%0" : "=r" (ret));
+  __asm __volatile__ ("movl cygtls_slot(%%rip),%%r10d\nmovq %%gs:0x1480(,%%r10d,8),%0" : "=r" (ret) : : "r10");
 #else
   __asm __volatile__ ("movl %%fs:4,%0" : "=r" (ret));
 #endif
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index 7787b164c..82b01b7aa 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -11,7 +11,7 @@ details. */
 #include "ntdll.h"
 #include "shared_info.h"
 
-static DWORD _my_oldfunc;
+DWORD NO_COPY cygtls_slot;
 
 static char *search_for  = (char *) cygthread::stub;
 unsigned threadfunc_ix[8];
@@ -25,7 +25,9 @@ __attribute__ ((force_align_arg_pointer))
 static void WINAPI
 threadfunc_fe (VOID *arg)
 {
-  _cygtls::call ((DWORD (*)  (void *, void *)) TlsGetValue (_my_oldfunc), arg);
+  PVOID f = TlsGetValue (cygtls_slot);
+  _set_tls();
+  _cygtls::call ((DWORD (*)  (void *, void *)) f, arg);
 }
 
 /* If possible, redirect the thread entry point to a cygwin routine which
@@ -62,7 +64,7 @@ munge_threadfunc ()
 	  for (i = 0; threadfunc_ix[i]; i++)
 	    if (!threadfunc || ebp[threadfunc_ix[i]] == threadfunc)
 	       ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
-	  TlsSetValue (_my_oldfunc, threadfunc);
+	  TlsSetValue (cygtls_slot, threadfunc);
 	}
     }
 }
@@ -81,6 +83,8 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
   switch (reason)
     {
     case DLL_PROCESS_ATTACH:
+      cygtls_slot = TlsAlloc ();
+      _set_tls();
       init_console_handler (false);
 
       cygwin_hmodule = (HMODULE) h;
@@ -97,7 +101,6 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
       memcpy (_REENT, _GLOBAL_REENT, sizeof (struct _reent));
 
       dll_crt0_0 ();
-      _my_oldfunc = TlsAlloc ();
       dll_finished_loading = true;
       break;
     case DLL_PROCESS_DETACH:
@@ -105,6 +108,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
 	shared_destroy ();
       break;
     case DLL_THREAD_ATTACH:
+      _set_tls();
       if (dll_finished_loading)
 	munge_threadfunc ();
       break;
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index cba2140b6..090eb4cca 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -378,6 +378,7 @@ pthread_wrapper (PVOID arg)
   /* Set stack values in TEB */
   PTEB teb = NtCurrentTeb ();
   teb->Tib.StackBase = wrapper_arg.stackbase;
+  _set_tls();
   teb->Tib.StackLimit = wrapper_arg.stacklimit ?: wrapper_arg.stackaddr;
   /* Set DeallocationStack value.  If we have an application-provided stack,
      we set DeallocationStack to NULL, so NtTerminateThread does not deallocate
@@ -647,6 +648,7 @@ create_new_main_thread_stack (PVOID &allocationbase, SIZE_T parent_commitsize)
     return NULL;
   NtCurrentTeb()->Tib.StackBase = ((PBYTE) allocationbase + stacksize);
   NtCurrentTeb()->Tib.StackLimit = stacklimit;
+  _set_tls();
   return ((PBYTE) allocationbase + stacksize - 16);
 }
 #endif
-- 
2.28.0

============================================================

This still needs work obviously:

- _set_tls() calls are scattered a little haphazardly
- the asm will only work if TlsAlloc gets one of the first 64 TLS slots
- I'm concerned about cygtls_slot being used before init (after fork?)

Anyone have any thoughts on this?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fibers and cygtls
  2020-09-04 15:13 Fibers and cygtls David McFarland
@ 2020-09-04 19:51 ` Corinna Vinschen
  2020-09-05  2:46   ` David McFarland
  2020-09-06 14:19 ` Jon Turney
  1 sibling, 1 reply; 6+ messages in thread
From: Corinna Vinschen @ 2020-09-04 19:51 UTC (permalink / raw)
  To: cygwin-developers

On Sep  4 12:13, David McFarland via Cygwin-developers wrote:
> For a while now I've been trying to get nix working on Cygwin. It
> compiles fine, but when it's run, it will exit unexpectedly in a way
> that doesn't return an error code to Cygwin, and doesn't break in gdb.
> 
> I tracked this to its use of boost coroutines, which use boost-context
> to switch fibers. boost-context can be built using either a custom asm
> implementation, or using windows fibers (CreateFiber).
> 
> Both the boost-context asm implementation and win32 fibers switch the
> NT_TIB StackBase and StackLimit fields (to a user provided buffer) when
> switching fibers. StackBase is used to find the cygtls for the current
> thread (in _my_tls, and with asm in gendef etc). Because of this, A
> program will crash when any syscall is made from a fiber.

Using Windows fibers verbatim is rather dangerous in the Cygwin context.

There are more problems than just the tls area on the thread stack.  If
you call CreateFiber, you get an arbitrary stack created by Windows.
The x86_64 stacks are all in reproducible slots in the thread stack area
starting at 0x080000000L.  One very important reason is that standard
Windows stacks tend to break reproducability at fork() time.  As for
the i686 stacks... never mind, it's hopeless anyway.

There's something vaguely similar inside Cygwin, the implementation
of the alternate signal stack (sigaltstack).  For a comment on how
this works see the comment in exceptions.cc, line 1726ff.  This may
(or may not) be a role model for implementing coroutine stacks.

Bottom line is, before trying to use Windows fibers, or before letting
boost use Windows functions on Cygwin (sigh), check what other POSIX or
BSD systems provide to implement coroutines.  If there's an API, let's
implement this API in Cygwin and then use that from user space.


Corinna

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Re: Fibers and cygtls
  2020-09-04 19:51 ` Corinna Vinschen
@ 2020-09-05  2:46   ` David McFarland
  2021-12-20 15:01     ` David McFarland
  0 siblings, 1 reply; 6+ messages in thread
From: David McFarland @ 2020-09-05  2:46 UTC (permalink / raw)
  To: cygwin-developers


> Bottom line is, before trying to use Windows fibers, or before letting
> boost use Windows functions on Cygwin (sigh), check what other POSIX or
> BSD systems provide to implement coroutines.  If there's an API, let's
> implement this API in Cygwin and then use that from user space.

boost-context doesn't actually use Windows fibers by default. Its fiber
implementation (fcontext) uses user-provided buffers for fiber stacks.

The jump implementation is in:

https://github.com/boostorg/context/blob/develop/src/asm/jump_x86_64_ms_pe_gas.asm

On Linux I believe uses its own asm implementation without any kernel
interaction:

https://github.com/boostorg/context/blob/develop/src/asm/jump_x86_64_sysv_elf_gas.S

There's also an implementation (ucontext) using makecontext, which may
be the best option. I'll try that next.

The implementations are compared here:

https://www.boost.org/doc/libs/1_74_0/libs/context/doc/html/context/cc/implementations__fcontext_t__ucontext_t_and_winfiber.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fibers and cygtls
  2020-09-04 15:13 Fibers and cygtls David McFarland
  2020-09-04 19:51 ` Corinna Vinschen
@ 2020-09-06 14:19 ` Jon Turney
  1 sibling, 0 replies; 6+ messages in thread
From: Jon Turney @ 2020-09-06 14:19 UTC (permalink / raw)
  To: cygwin-developers; +Cc: David McFarland

On 04/09/2020 16:13, David McFarland via Cygwin-developers wrote:
> For a while now I've been trying to get nix working on Cygwin. It
> compiles fine, but when it's run, it will exit unexpectedly in a way
> that doesn't return an error code to Cygwin, and doesn't break in gdb.

I think this probably means you need to use 'set cygwin-exceptions on' 
in gdb. (See [1]).

[1] https://cygwin.com/faq.html#faq.programming.debugging-cygwin

(Yes, gdb could be a lot smarter about what it chooses to ignore)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fibers and cygtls
  2020-09-05  2:46   ` David McFarland
@ 2021-12-20 15:01     ` David McFarland
  2021-12-22 15:46       ` David McFarland
  0 siblings, 1 reply; 6+ messages in thread
From: David McFarland @ 2021-12-20 15:01 UTC (permalink / raw)
  To: cygwin-developers; +Cc: corngood

> > Bottom line is, before trying to use Windows fibers, or before letting
> > boost use Windows functions on Cygwin (sigh), check what other POSIX or
> > BSD systems provide to implement coroutines.  If there's an API, let's
> > implement this API in Cygwin and then use that from user space.
> 
> There's also an implementation (ucontext) using makecontext, which may
> be the best option. I'll try that next.

I've been at this on-and-off since my last message.  I tried the
ucontext-based implementation of coroutines in boost, but unfortunately
ucontext seems to break exceptions.

The only reference I could find to this was:

https://stackoverflow.com/questions/30725276/modifying-the-stack-on-windows-tib-and-exceptions

> On a related note, I wondered how Cygwin dealt with this for ucontext.
> The source here
> http://szupervigyor.ddsi.hu/source/in/openjdk-6-6b18-1.8.13/cacao-0.99.4/src/vm/jit/i386/cygwin/ucontext.c
> uses GetThreadContext/SetThreadContext to implement ucontext. However,
> from experimentation I see that this also fails when an exception is
> thrown from inside a new context. In fact the SetThreadContext call
> doesn't even update the TIB block!

This seems to match what I'm seeing. The boost unit tests fail with
ucontext, seemingly because the exception handlers are wrong after
switching contexts. They pass using fcontext, but only if I apply the
TLS patches I shared here:

https://cygwin.com/pipermail/cygwin-developers/2020-September/011970.html

Here's a test program:

test-context.cc:
=====
#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>

static ucontext_t uctx_main, uctx_func1;

#define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

struct test_ex {};

static void func1(void) {
    try {
        printf("func1: throw\n");
        throw test_ex();
    } catch(test_ex const&) {
        printf("func1: caught\n");
    }
    printf("func1: swapcontext(&uctx_func1, &uctx_main)\n");
    if (swapcontext(&uctx_func1, &uctx_main) == -1)
        handle_error("swapcontext");
}

const size_t stack_size = 16 * 1024;

void test (char *stack) {
    if (getcontext(&uctx_func1) == -1)
        handle_error("getcontext");
    uctx_func1.uc_stack.ss_sp = stack;
    uctx_func1.uc_stack.ss_size = stack_size;
    uctx_func1.uc_link = &uctx_main;
    makecontext(&uctx_func1, func1, 0);

    printf("main: swapcontext(&uctx_main, &uctx_func1)\n");
    if (swapcontext(&uctx_main, &uctx_func1) == -1)
        handle_error("swapcontext");
}

int main(int argc, char *argv[])
{
    char on_stack[stack_size];
    test(on_stack);

    char *from_malloc = (char*)malloc(stack_size);
    test(from_malloc);

    printf("main: exiting\n");
    exit(EXIT_SUCCESS);
}
=====

When the stack provided to makecontext is allocated on the main thread
stack, it works, but when the stack is allocated via malloc, weird stuff
happens:

When run from a shell it just exits with 0 when the exception is thrown.
This is of particular concern because it may be causing e.g. boost unit
tests to fail silently.

With gdb attached (with or without cygwin-exceptions enabled):

> func1: throw
> gdb: unknown target exception 0x20474343 at 0x7ffca0da4f69
> 
> Thread 1 "test-context" received signal ?, Unknown signal.
> 0x00007ffca0da4f69 in RaiseException () from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
> (gdb) bt
> #0  0x00007ffca0da4f69 in RaiseException () from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
> #1  0x00000003ffabcca1 in _Unwind_RaiseException (exc=<optimized out>) at /usr/src/debug/gcc-11.2.0-1/libgcc/unwind-seh.c:334
> #2  0x00000003fd067f1b in __cxxabiv1::__cxa_throw (obj=<optimized out>, tinfo=0x1004030c0 <__fu0__ZTVN10__cxxabiv117__class_type_infoE>, dest=0x0) at /usr/src/debug/gcc-11.2.0-1/libstdc++-v3/libsupc++/eh_throw.cc:90
> #3  0x00000001004010b9 in func1 () at test-context.cc:15
> #4  0x0000000180068fac in swapcontext (oucp=0x0, ucp=0x0) at ../../../../winsup/cygwin/exceptions.cc:1935
> #5  0x0000000100407000 in ?? ()
> #6  0x0000000000000000 in ?? ()
> Backtrace stopped: previous frame inner to this frame (corrupt stack?)
> (gdb) c
> Continuing.
> [Thread 11348.0x2fa0 exited with code 541541187]
> [Thread 11348.0x2bec exited with code 541541187]
> [Thread 11348.0xd50 exited with code 541541187]
> [Thread 11348.0xacc exited with code 541541187]
> 
> Program terminated with signal ?, Unknown signal.
> The program no longer exists.

With strace:

> func1: throw
>   680  409603 [main] test-context 1515 fhandler_console::write: 13 = fhandler_console::write(...)
>  1123  410726 [main] test-context 1515 write: 13 = write(1, 0x80005C2B0, 13)
> --- Process 1724 (pid: 1515) thread 5548 exited with status 0x20474343
> --- Process 1724 (pid: 1515) thread 10792 exited with status 0x20474343
> --- Process 1724 (pid: 1515) thread 2568 exited with status 0x20474343
> --- Process 1724 (pid: 1515) thread 12124 exited with status 0x20474343
> --- Process 1724 (pid: 1515) exited with status 0x20474343

I assume this has something to do with the stack still being in the
valid range in the TIB?

My goal here is to get nix working on cygwin. It depends on boost
coroutines, which can use ucontext, but it uses malloc to allocate heaps
by default.

Anyone have any thoughts on how I could proceed? For now I'll keep
digging into exception handling and context switching.

Cheers,
Dave

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fibers and cygtls
  2021-12-20 15:01     ` David McFarland
@ 2021-12-22 15:46       ` David McFarland
  0 siblings, 0 replies; 6+ messages in thread
From: David McFarland @ 2021-12-22 15:46 UTC (permalink / raw)
  To: cygwin-developers

David McFarland <corngood@gmail.com> writes:

> This seems to match what I'm seeing. The boost unit tests fail with
> ucontext, seemingly because the exception handlers are wrong after
> switching contexts. They pass using fcontext, but only if I apply the
> TLS patches I shared here:
>
> https://cygwin.com/pipermail/cygwin-developers/2020-September/011970.html

ucontext appears to have the opposite problem as the other fiber
implementations (boost fcontext, windows fibers).  The TIB StackBase and
StackLimit are never changed, so cygtls is still accessible, but windows
stuff (including exception handling on x64?) is broken.

It's possible it could be fixed by storing cygtls in windows TLS, and
setting StackBase/Limit in setcontext.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-12-22 15:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-04 15:13 Fibers and cygtls David McFarland
2020-09-04 19:51 ` Corinna Vinschen
2020-09-05  2:46   ` David McFarland
2021-12-20 15:01     ` David McFarland
2021-12-22 15:46       ` David McFarland
2020-09-06 14:19 ` Jon Turney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).