Introduction
------------

Version 2 of CyPari for Windows is built using MSys2 and the mingw32
gcc toolchain.  It passes the doctests at essentially the same rate as
the linux and macOS versions, and supports SIGINT interrupts via
control-C.  However, there are some caveats:

1) The mingw32 toolchain must be modified to produce a Python
extension module which does not segfault while being loaded.  (See the
explanation in "About Segfaults" below.)  To deal with this issue, the
script install_files_32.sh in the toolchain directory adds the needed
files to your mingw32 toolchain.  (The mingw64 version has not been
tested, but may work.)

2) To be able to interrupt a long computation by typing control-C
requires two non-trivial things: (i) the module must have appropriate
SIGINT handlers and (see "About longjmp" below); and (ii) the terminal
must send a SIGINT signal (see "About SIGINT" below).  The caveat here
is that the Cygwin Mintty terminal provided with MSys2 does not handle
sending a SIGINT in the same way as the Windows console, which causes
different behavior. More importantly, it is not possible to run python
interactively in Mintty at all, unless you run the python process
within a winpty wrapper:
$ winpty python

One way to handle this is to add something like the following to the
end of the .bash_profile in your msys2 home directory:

export PATH="/c/Python27:/c/Python27/Scripts:/c/emacs-2.4.v/bin:/c/Program Files (x86)/Common Files/Microsoft/Visual C++ for Python/9.0/VC/bin:$PATH"
winpty bash; exit

(The second line runs bash in a winpty wrapper and exits when that shell
is killed.)

About Segfaults
---------------

When I first built this package and tested it, Python segfaulted while
loading the module.  With great effort I finally identified the point
where the crash occurred.  It was crashing when calling realloc in the
function initprimes (src/language/forprimes.c.  This routine first
calls malloc to allocate a block of memory which is provably large
enough to hold a table with the desired number of primes, then writes
the primes into the table, and finally calls realloc to reduce the
size of the block to the size of the table.  How could this fail?

The answer is that the malloc function was coming from the C runtime
in msvcr90.dll while the realloc function was coming from the older
C runtime msvcrt.dll.  The Python executable was linked against the
former while mingw2 uses the latter as its default runtime.  The two
runtimes are not compatible.  When Python loads, it needs malloc so
it resolves the malloc symbol against msvcr90.dll.  However, it does
not immediately use realloc, so that symbol remains unresolved.  When
the cypari extension module is loaded it inherits the malloc from
Python, but it does not inherit realloc since that is still
unresolved.  When realloc is needed in initprimes, the symbol is
resolved against the msvcrt.dll.  The two runtimes do not allocate
memory in compatible ways - hence the segfault.

There is a reason why mingw32 uses the out-of-date msvcrt runtime, and
it has to do with Microsoft's attempt to deal with the "DLL Hell"
caused by having many incompatible DLL's on the same system, all with
the same name.  Their solution was called "Side by Side Assemblies"
which consist of a DLL, which has been assigned a cryprographic key
uniquely identifying its precise version, and an xml "Manifest file"
which specifies the key.  These must appear in the same subdirectory
of the C:\Windows\winsxs directory.  In order for a third party DLL or
EXE to call functions from a dll in a side-by-side assemply, the
library must have its own manifest file which matches the one in
winsxs.  This user manifest file must either appear in the same
directory as the DLL or EXE, or else be embedded in it as a Windows
"Resource".  The gcc linker is able to embed these resource files, if
they are supplied on the command line.

So, to ensure that our cypari extension module gets its C runtime
functions from the same DLL as the Python executable we need to do two
things (and possible a third, even more technical one).  First, we
need to prevent gcc from linking against its default msvcrt runtime.
This is done by providing gcc with a "specs" file which specifies
things such as which "hidden" link libraries (e.g. C runtimes) are
linked before the user-supplied libraries.  Our specs file specifies
that gcc should link agains the msvcr90 runtime. Second, we need to
provide a resource file that matches the msvcr90 runtime so that the
OS will allow the extension module to access the runtime.  The final
technical item is that one of the hidden libraries, called
libmoldname, which has the job of mapping names of runtime functions
to the older name which has an underscore prepended, probably has to
be replaced with one that has symbols matching msvcr90 instead of
msvcrt.  To accomplish all this we need to add three files to the
mingw32 toolchain.  Thes files are named specs90, mscvr90.res and
libmoldname90.a. In addition, to make gcc use the specs file, we need
to pass the option specs=specs90 to the mingw32 linker.  Our spec
file is a modified version of the one developed by the mingwpy
project (https://mingwpy.github.io/).  Instructions for using the
gnu dlltool to build libmoldname90.a can be found on the pygame
website (http://www.pygame.org/wiki/PreparingMinGW).  The tool used
to convert an xml file to a windows resource is called windres
(see http://www.mingw.org/wiki/MS_resource_compiler).  The structure
of a manifest file is described on the Microsoft developer site
(https://msdn.microsoft.com/en-us/library/windows/desktop/aa375365(v=vs.85).aspx).

About longjmp
-------------

Sage's sig_on and sig_off macros are based on the setjmp/longjmp
paradigm (or, on posix systems, sigsetjmp/siglongjmp).  This low level
paradigm is an early precursor of the try - except blocks in high
level languages.  It is commonly used in combination with signal
handlers.  The basic construction looks like this:

if (setjmp(env) == 0) {
   ... long running interruptible code
   }
... go on from here ...   

The setjmp function saves a copy of the current stack frame in the
global struct env and returns 0.  If one wants to be able to interrupt
the long running code one needs a signal handler like this:

void handler(int signum) {
  ... do something ...
  longjmp(env, signum); /* never returns */
}

The effect of the call to longjmp is to use the saved frame to
reconstruct the stack so it is in the same state that it would have
been in if the function setjmp had returned the value signum instead
of 0, and then coninue execution at the next instruction past the
longjmp.  Thus when the signal handler returns, the program executes as
if it had simply skipped the entire block of long running code.  The
return value of setjmp can be used to determine how to recover from
the interrupt.

There are many things that can go wrong with this.  The typical error
is to call setjmp from a function which returns before the call to
longjmp.  This inserts a stack frame at a random point in the stack,
resulting is a totally trashed stack and a big crash.

One thing to notice about this paradigm is that it assumes that the
signal handler is running on the same stack as the main program.
While this is not a posix requirement, it is true for most posix
systems including linux and macOS.  But it is NOT true for Windows.
In Windows, the signal handler runs in a separate thread with its own
stack and has no way of accessing the stack of its parent
process. However, it turns out that there is (exactly) one special
signal for which Windows supports using longjmp in the handler, namely
SIGFPE.  This is explicitly stated in the Windows documentation:
https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx
https://msdn.microsoft.com/en-us/library/aa246458(v=vs.60).aspx

We take advantage of this quirk to port the cysignals package to
Windows.  When our handler is called with a different signal than
SIGFPE, it stores the signal number in the global cysigs structure and
raises SIGFPE. (This means we are raising a signal within a signal
handler, which would be a no-no in posix but appears to be OK in
Windows.)  When the handler is called with SIGFPE it chacks the cysigs
structure and responds appropriately (no stored signal means that it
is a real SIGFPE).

About SIGINT
------------

In Windows it is not supported for one process to use signals to
communicate with another.  In posix the "kill" function does not
necessarily terminate the target process, it just sends it a signal.
But Windows takes "kill" very literally.  The target process will be
terminated after receiving the signal, no matter what.  The only use
of the signal number when a process gets "killed" by another is for
deciding which cleanup routine to call before termination.

However, there is another class of things which behave similarly to
signals.  Perhaps they should be called "events" since there only two
that I know of: CTRL_C_EVENT and CTRL_BREAK_EVENT.  These events can
have handlers, just like signals.  Windows has two distinct types of
proecesses, "Console" processes and "Gui" processes, and only Console
processes support these events.  The Windows Command Prompt knows how
to deliver these eponymous "events" in response to the keystokes in
their name.  As far as I can tell, other consoles cannot do this,
MinTTY being the prime example.  This is why it is not a trivial
matter to arrange for delivery of a SIGINT signal when you want to
interrupt a long-running computation.  (I believe that the original
MSys terminal was actually a subclass of the same object as the CONS:
Command Prompt, and that is why it was able to supply the SIGINT.  If
a terminal can initiate a CTRL_C_EVENT, then one can create a
CTRL-C-EVENT handler which raises SIGINT.
