From 04fa6c6acdf7b6b41772cf973b3aa2a63f6964a0 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 5 Jul 2010 14:48:16 -0600 Subject: [PATCH] add `subprocess-group-enabled' for process-group support and fix problems with places and subprocesses and fix some mzrt thread setup and teardown issues --- .../scribblings/reference/subprocess.scrbl | 120 +++- collects/tests/racket/subprocess.rktl | 39 + src/racket/gc2/newgc.c | 3 + src/racket/gc2/vm_osx.c | 32 +- src/racket/include/scheme.h | 1 + src/racket/src/cstartup.inc | 670 +++++++++--------- src/racket/src/env.c | 6 +- src/racket/src/mzrt.c | 57 +- src/racket/src/mzrt.h | 1 + src/racket/src/places.c | 369 ++++++++-- src/racket/src/port.c | 219 ++++-- src/racket/src/salloc.c | 17 + src/racket/src/schminc.h | 2 +- src/racket/src/schpriv.h | 14 +- src/racket/src/schvers.h | 4 +- src/racket/src/thread.c | 6 +- 16 files changed, 1051 insertions(+), 509 deletions(-) diff --git a/collects/scribblings/reference/subprocess.scrbl b/collects/scribblings/reference/subprocess.scrbl index 284e0b84ce..3f6628a0fa 100644 --- a/collects/scribblings/reference/subprocess.scrbl +++ b/collects/scribblings/reference/subprocess.scrbl @@ -82,9 +82,18 @@ the current custodian (see @secref["custodians"]). The process or the creation of operating system pipes for process communication. +If the @racket[subprocess-group-enabled] parameter's value is true, +then the new process is created as a new OS-level process group. In +that case, @racket[subprocess-kill] attempts to terminate all +processes within the group, which may include additional processes +created by the subprocess. See @racket[subprocess-kill] for details, +and see @racket[subprocess-group-enabled] for additional caveats. + The @racket[current-subprocess-custodian-mode] parameter determines whether the subprocess itself is registered with the current -custodian.} +@tech{custodian} so that a custodian shutdown calls +@racket[subprocess-kill] for the subprocess.} + @defproc[(subprocess-wait [subproc subprocess?]) void?]{ @@ -106,21 +115,56 @@ code is non-zero.} @defproc[(subprocess-kill [subproc subprocess?] [force? any/c]) void?]{ -Terminates the subprocess represented by @racket[subproc] if -@racket[force?] is true and if the process still running. If an error -occurs during termination, the @exnraise[exn:fail]. +Terminates the subprocess represented by @racket[subproc]. The precise +action depends on whether @racket[force?] is true, whether the process +was created in its own group by setting the +@racket[subprocess-group-enabled] parameter to a true value, and the +current platform: -If @racket[force?] is @racket[#f] under @|AllUnix|, the subprocess is -sent an interrupt signal instead of a kill signal (and the subprocess -might handle the signal without terminating). Under Windows, no action -is taken when @racket[force?] is @racket[#f].} +@itemlist[ + + @item{@racket[force?] is true, not a group, all platforms: Terminates + the process if the process still running.} + + @item{@racket[force?] is false, not a group, under Unix or Mac OS X: + Sends the process an interrupt signal instead of a kill + signal.} + + @item{@racket[force?] is false, not a group, under Windows: No action + is taken.} + + @item{@racket[force?] is true, a group, under Unix or Mac OS X: + Terminates all processes in the group, but only if + @racket[subprocess-status] has never produced a + non-@racket['running] result for the subprocess and only if + functions like @racket[subprocess-wait] and @racket[sync] have + not detected the subprocess's completion. Otherwise, no action + is taken (because the immediate process is known to have + terminated while the continued existence of the group is + unknown).} + + @item{@racket[force?] is true, a group, under Windows: Terminates + the process if the process still running.} + + @item{@racket[force?] is false, a group, under Unix or Mac OS X: The + same as when @racket[force?] is @scheme[#t], but when the group + is sent a signal, it is an interrupt signal instead of a kill + signal.} + + @item{@racket[force?] is false, a group, under Windows: All processes + in the group receive a CTRL-BREAK signal (independent of + whether the immediate subprocess has terminated).} + +] + +If an error occurs during termination, the @exnraise[exn:fail].} -@defproc[(subprocess-pid [subproce subprocess?]) exact-nonnegative-integer?]{ +@defproc[(subprocess-pid [subproc subprocess?]) exact-nonnegative-integer?]{ Returns the operating system's numerical ID (if any) for the process -represented by @racket[subproc], valid only as long as the process is -running.} +represented by @racket[subproc]. The result is valid only as long as +the process is running.} @defproc[(subprocess? [v any/c]) boolean?]{ @@ -131,22 +175,35 @@ otherwise.} @defparam[current-subprocess-custodian-mode mode (or/c #f 'kill 'interrupt)]{ -Determines whether a subprocess (as created by @racket[subprocess] or -wrappers like @racket[process]) is registered with the current -@tech{custodian}. If the parameter value is @racket[#f], then the subprocess -is not registered with the custodian---although any created ports are -registered. If the parameter value is @racket['kill] or -@racket['interrupt], then the subprocess is shut down through -@racket[subprocess-kill], where @racket['kill] supplies a @racket[#t] -value for the @racket[_force?] argument and @racket['interrupt] -supplies a @racket[#f] value. The shutdown may occur either before or -after ports created for the subprocess are closed. +A @tech{parameter} that determines whether a subprocess (as created by +@racket[subprocess] or wrappers like @racket[process]) is registered +with the current @tech{custodian}. If the parameter value is +@racket[#f], then the subprocess is not registered with the +custodian---although any created ports are registered. If the +parameter value is @racket['kill] or @racket['interrupt], then the +subprocess is shut down through @racket[subprocess-kill], where +@racket['kill] supplies a @racket[#t] value for the @racket[_force?] +argument and @racket['interrupt] supplies a @racket[#f] value. The +shutdown may occur either before or after ports created for the +subprocess are closed. Custodian-triggered shutdown is limited by details of process handling in the host system. For example, @racket[process] and @racket[system] may create an intermediate shell process to run a program, in which case custodian-based termination shuts down the shell process and -probably not the process started by the shell.} +probably not the process started by the shell. See also +@racket[subprocess-kill]. Process groups (see +@racket[subprocess-group-enabled]) can address some limitations, but +not all of them.} + + +@defboolparam[subprocess-group-enabled on?]{ + +A @tech{parameter} that determines whether a subprocess is created as +a new process group. See @racket[subprocess-kill] for more information. + +Beware that creating a group may interfere with the job control in an +interactive shell, since job control is based on process groups.} @defproc[(shell-execute [verb (or/c string? #f)] @@ -154,7 +211,7 @@ probably not the process started by the shell.} [parameters string?] [dir path-string?] [show-mode symbol?]) - #f] + #f]{ @index['("ShellExecute")]{Performs} the action specified by @racket[verb] on @racket[target] in Windows. For platforms other than Windows, the @@ -246,7 +303,7 @@ the result is @racket[#f]. In future versions of Racket, the result may be a subprocess value if the operating system did returns a process handle (but if a subprocess value is returned, its process ID will be @racket[0] instead of the -real process ID). +real process ID).} @; ---------------------------------------------------------------------- @@ -260,7 +317,11 @@ Executes a Unix, Mac OS X, or Windows shell command synchronously (i.e., the call to @racket[system] does not return until the subprocess has ended). The @racket[command] argument is a string containing no nul characters. If the command succeeds, the return -value is @racket[#t], @racket[#f] otherwise.} +value is @racket[#t], @racket[#f] otherwise. + +See also @racket[current-subprocess-custodian-mode] and +@racket[subprocess-group-enabled], which affect the subprocess used to +implement @racket[system].} @defproc*[([(system* [command path-string?] [arg string?] ...) boolean?] @@ -349,7 +410,14 @@ values: @bold{Important:} All three ports returned from @racket[process] must be explicitly closed with @racket[close-input-port] or -@racket[close-output-port].} +@racket[close-output-port]. + +See also @racket[current-subprocess-custodian-mode] and +@racket[subprocess-group-enabled], which affect the subprocess used to +implement @racket[process]. In particular, the @racket['interrupt] and +@racket['kill] process-control messages are implemented via +@racket[subprocess-kill], so they can affect a process group instead +of a single process.} @defproc*[([(process* [command path-string?] [arg string?] ...) list?] diff --git a/collects/tests/racket/subprocess.rktl b/collects/tests/racket/subprocess.rktl index 33fee9d391..2cd91777b2 100644 --- a/collects/tests/racket/subprocess.rktl +++ b/collects/tests/racket/subprocess.rktl @@ -285,6 +285,45 @@ (parameterize ([current-subprocess-custodian-mode 'interrupt]) (try (if (eq? 'windows (system-type)) 'running 'done-error)))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; process groups +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(unless (eq? 'windows (system-type)) + (let ([try + (lambda (post-shutdown?) + (let ([l (parameterize ([subprocess-group-enabled (not post-shutdown?)]) + (process* self + "-e" + (format "(define l (process* \"~a\" \"-e\" \"(let loop () (loop))\"))" self) + "-e" + "(displayln (list-ref l 2))" + "-e" + "(flush-output)" + "-e" + "(let loop () (loop))"))] + [running? (lambda (sub-pid) + (equal? + (list (number->string sub-pid)) + (regexp-match + (format "(?m:^~a(?=[^0-9]))" sub-pid) + (let ([s (open-output-string)]) + (parameterize ([current-output-port s]) + (system (format "ps x"))) + (get-output-string s)))))]) + (let ([sub-pid (read (car l))]) + (test 'running (list-ref l 4) 'status) + (test #t running? sub-pid) + ((list-ref l 4) 'kill) + ((list-ref l 4) 'wait) + (test 'done-error (list-ref l 4) 'status) + (test post-shutdown? running? sub-pid) + (when post-shutdown? + (system (format "kill ~a" sub-pid))))))]) + (try #t) + (try #f))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/src/racket/gc2/newgc.c b/src/racket/gc2/newgc.c index 3868c24764..75e5f2de35 100644 --- a/src/racket/gc2/newgc.c +++ b/src/racket/gc2/newgc.c @@ -2040,12 +2040,15 @@ static void NewGCMasterInfo_initialize() { mzrt_sema_create(&MASTERGCINFO->wait_sema, 0); } +#if 0 +/* Not yet used: */ static void NewGCMasterInfo_cleanup() { mzrt_rwlock_destroy(MASTERGCINFO->cangc); free(MASTERGCINFO->signal_fds); free(MASTERGCINFO); MASTERGCINFO = NULL; } +#endif /* signals every place to do a full gc at then end of garbage_collect the places will call diff --git a/src/racket/gc2/vm_osx.c b/src/racket/gc2/vm_osx.c index c715e2879f..73466e621e 100644 --- a/src/racket/gc2/vm_osx.c +++ b/src/racket/gc2/vm_osx.c @@ -41,7 +41,7 @@ int designate_modified(void *p); # define THREAD_FLD(x) x #endif -#if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) +#if defined(MZ_USE_PLACES) typedef struct OSXThreadData { struct OSXThreadData *next; mach_port_t thread_port_id; @@ -97,6 +97,25 @@ static void register_mach_thread() { pthread_mutex_unlock(&osxthreadsmutex); } +static void unregister_mach_thread() { + mach_port_t thread_self = mach_thread_self(); + int index = thread_self % OSX_THREAD_TABLE_SIZE; + OSXThreadData * thread, *prev = NULL; + + thread = osxthreads[index]; + while (thread->thread_port_id != thread_self) { + prev = thread; + thread = thread->next; + } + if (thread) { + if (prev) + prev->next = thread->next; + else + osxthreads[index] = thread->next; + free(thread); + } +} + #endif #if defined(__POWERPC__) @@ -290,7 +309,7 @@ kern_return_t GC_catch_exception_raise(mach_port_t port, p = (void *)exc_state. THREAD_FLD(faultvaddr); #endif -#if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) +#if defined(MZ_USE_PLACES) set_thread_locals_from_mach_thread_id(thread_port); #endif @@ -373,11 +392,18 @@ void GC_attach_current_thread_exceptions_to_handler() GCPRINT(GCOUTF, "Couldn't set exception ports: %s\n", mach_error_string(retval)); abort(); } -#if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) +#if defined(MZ_USE_PLACES) register_mach_thread(); #endif } +void GC_detach_current_thread_exceptions_from_handler() +{ +#if defined(MZ_USE_PLACES) + unregister_mach_thread(); +#endif +} + /* this initializes the subsystem (sets the exception port, starts the exception handling thread, etc) */ static void macosx_init_exception_handler(int isMASTERGC) diff --git a/src/racket/include/scheme.h b/src/racket/include/scheme.h index e141deb376..76e1a6e9da 100644 --- a/src/racket/include/scheme.h +++ b/src/racket/include/scheme.h @@ -1256,6 +1256,7 @@ enum { MZCONFIG_THREAD_INIT_STACK_SIZE, MZCONFIG_SUBPROC_CUSTODIAN_MODE, + MZCONFIG_SUBPROC_GROUP_ENABLED, MZCONFIG_LOAD_DELAY_ENABLED, MZCONFIG_DELAY_LOAD_INFO, diff --git a/src/racket/src/cstartup.inc b/src/racket/src/cstartup.inc index 842bd431d2..8281967a14 100644 --- a/src/racket/src/cstartup.inc +++ b/src/racket/src/cstartup.inc @@ -1,5 +1,5 @@ { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,54,51,0,0,0,1,0,0,10,0,13,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,55,51,0,0,0,1,0,0,10,0,13,0, 22,0,27,0,40,0,47,0,51,0,55,0,58,0,65,0,72,0,77,0,82, 0,88,0,102,0,116,0,119,0,125,0,129,0,131,0,142,0,144,0,158,0, 165,0,187,0,189,0,203,0,14,1,43,1,54,1,65,1,75,1,111,1,144, @@ -61,10 +61,10 @@ 110,117,97,116,105,111,110,45,109,97,114,107,45,115,101,116,45,102,105,114,115, 116,11,2,25,201,250,22,82,2,21,9,248,22,73,203,27,248,22,73,248,22, 147,4,196,28,248,22,79,193,20,15,159,37,36,37,249,22,140,4,80,158,39, -36,27,248,22,147,4,248,22,72,197,28,249,22,184,8,62,61,62,248,22,141, +36,27,248,22,147,4,248,22,72,197,28,249,22,185,8,62,61,62,248,22,141, 4,248,22,96,196,250,22,81,2,21,248,22,81,249,22,81,21,93,2,26,248, 22,72,199,250,22,82,2,4,249,22,81,2,26,249,22,81,248,22,105,203,2, -26,248,22,73,202,251,22,81,2,17,28,249,22,184,8,248,22,141,4,248,22, +26,248,22,73,202,251,22,81,2,17,28,249,22,185,8,248,22,141,4,248,22, 72,200,64,101,108,115,101,10,248,22,72,197,250,22,82,2,21,9,248,22,73, 200,249,22,71,2,4,248,22,73,202,100,8,32,8,31,8,30,8,29,8,28, 16,4,11,11,2,19,3,1,8,101,110,118,49,50,56,54,51,16,4,11,11, @@ -99,7 +99,7 @@ EVAL_ONE_SIZED_STR((char *)expr, 2024); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,54,65,0,0,0,1,0,0,8,0,21,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,55,65,0,0,0,1,0,0,8,0,21,0, 26,0,43,0,58,0,76,0,92,0,102,0,120,0,140,0,156,0,174,0,205, 0,234,0,0,1,14,1,20,1,34,1,39,1,49,1,57,1,85,1,117,1, 123,1,168,1,213,1,237,1,20,2,22,2,188,2,22,4,63,4,136,5,222, @@ -132,234 +132,234 @@ 111,114,32,98,121,116,101,32,115,116,114,105,110,103,6,36,36,99,97,110,110, 111,116,32,97,100,100,32,97,32,115,117,102,102,105,120,32,116,111,32,97,32, 114,111,111,116,32,112,97,116,104,58,32,5,0,27,20,14,159,80,159,37,51, -38,250,80,159,40,52,38,249,22,27,11,80,159,42,51,38,22,157,13,10,248, -22,175,5,23,196,2,28,248,22,172,6,23,194,2,12,87,94,248,22,190,8, +38,250,80,159,40,52,38,249,22,27,11,80,159,42,51,38,22,158,13,10,248, +22,176,5,23,196,2,28,248,22,173,6,23,194,2,12,87,94,248,22,191,8, 23,194,1,27,20,14,159,80,159,38,51,38,250,80,159,41,52,38,249,22,27, -11,80,159,43,51,38,22,157,13,10,248,22,175,5,23,197,2,28,248,22,172, -6,23,194,2,12,87,94,248,22,190,8,23,194,1,27,20,14,159,80,159,39, -51,38,250,80,159,42,52,38,249,22,27,11,80,159,44,51,38,22,157,13,10, -248,22,175,5,23,198,2,28,248,22,172,6,23,194,2,12,87,94,248,22,190, +11,80,159,43,51,38,22,158,13,10,248,22,176,5,23,197,2,28,248,22,173, +6,23,194,2,12,87,94,248,22,191,8,23,194,1,27,20,14,159,80,159,39, +51,38,250,80,159,42,52,38,249,22,27,11,80,159,44,51,38,22,158,13,10, +248,22,176,5,23,198,2,28,248,22,173,6,23,194,2,12,87,94,248,22,191, 8,23,194,1,248,80,159,40,54,37,197,28,248,22,79,23,195,2,9,27,248, -22,72,23,196,2,27,28,248,22,141,14,23,195,2,23,194,1,28,248,22,140, -14,23,195,2,249,22,142,14,23,196,1,250,80,158,43,49,248,22,157,14,2, -20,11,10,250,80,158,41,49,248,22,157,14,2,20,23,197,1,10,28,23,193, -2,249,22,71,248,22,144,14,249,22,142,14,23,198,1,247,22,158,14,27,248, +22,72,23,196,2,27,28,248,22,142,14,23,195,2,23,194,1,28,248,22,141, +14,23,195,2,249,22,143,14,23,196,1,250,80,158,43,49,248,22,158,14,2, +20,11,10,250,80,158,41,49,248,22,158,14,2,20,23,197,1,10,28,23,193, +2,249,22,71,248,22,145,14,249,22,143,14,23,198,1,247,22,159,14,27,248, 22,73,23,200,1,28,248,22,79,23,194,2,9,27,248,22,72,23,195,2,27, -28,248,22,141,14,23,195,2,23,194,1,28,248,22,140,14,23,195,2,249,22, -142,14,23,196,1,250,80,158,48,49,248,22,157,14,2,20,11,10,250,80,158, -46,49,248,22,157,14,2,20,23,197,1,10,28,23,193,2,249,22,71,248,22, -144,14,249,22,142,14,23,198,1,247,22,158,14,248,80,159,46,53,37,248,22, +28,248,22,142,14,23,195,2,23,194,1,28,248,22,141,14,23,195,2,249,22, +143,14,23,196,1,250,80,158,48,49,248,22,158,14,2,20,11,10,250,80,158, +46,49,248,22,158,14,2,20,23,197,1,10,28,23,193,2,249,22,71,248,22, +145,14,249,22,143,14,23,198,1,247,22,159,14,248,80,159,46,53,37,248,22, 73,23,199,1,87,94,23,193,1,248,80,159,44,53,37,248,22,73,23,197,1, 87,94,23,193,1,27,248,22,73,23,198,1,28,248,22,79,23,194,2,9,27, -248,22,72,23,195,2,27,28,248,22,141,14,23,195,2,23,194,1,28,248,22, -140,14,23,195,2,249,22,142,14,23,196,1,250,80,158,46,49,248,22,157,14, -2,20,11,10,250,80,158,44,49,248,22,157,14,2,20,23,197,1,10,28,23, -193,2,249,22,71,248,22,144,14,249,22,142,14,23,198,1,247,22,158,14,248, +248,22,72,23,195,2,27,28,248,22,142,14,23,195,2,23,194,1,28,248,22, +141,14,23,195,2,249,22,143,14,23,196,1,250,80,158,46,49,248,22,158,14, +2,20,11,10,250,80,158,44,49,248,22,158,14,2,20,23,197,1,10,28,23, +193,2,249,22,71,248,22,145,14,249,22,143,14,23,198,1,247,22,159,14,248, 80,159,44,53,37,248,22,73,23,199,1,248,80,159,42,53,37,248,22,73,196, -27,248,22,181,13,23,195,2,28,23,193,2,192,87,94,23,193,1,28,248,22, -177,6,23,195,2,27,248,22,139,14,195,28,192,192,248,22,140,14,195,11,87, -94,28,28,248,22,182,13,23,195,2,10,28,248,22,181,13,23,195,2,10,28, -248,22,177,6,23,195,2,28,248,22,139,14,23,195,2,10,248,22,140,14,23, -195,2,11,12,250,22,154,9,76,110,111,114,109,97,108,45,112,97,116,104,45, +27,248,22,182,13,23,195,2,28,23,193,2,192,87,94,23,193,1,28,248,22, +178,6,23,195,2,27,248,22,140,14,195,28,192,192,248,22,141,14,195,11,87, +94,28,28,248,22,183,13,23,195,2,10,28,248,22,182,13,23,195,2,10,28, +248,22,178,6,23,195,2,28,248,22,140,14,23,195,2,10,248,22,141,14,23, +195,2,11,12,250,22,155,9,76,110,111,114,109,97,108,45,112,97,116,104,45, 99,97,115,101,6,42,42,112,97,116,104,32,40,102,111,114,32,97,110,121,32, 115,121,115,116,101,109,41,32,111,114,32,118,97,108,105,100,45,112,97,116,104, -32,115,116,114,105,110,103,23,197,2,28,28,248,22,182,13,23,195,2,249,22, -184,8,248,22,183,13,23,197,2,2,21,249,22,184,8,247,22,133,8,2,21, -27,28,248,22,177,6,23,196,2,23,195,2,248,22,187,7,248,22,186,13,23, -197,2,28,249,22,172,14,0,21,35,114,120,34,94,91,92,92,93,91,92,92, -93,91,63,93,91,92,92,93,34,23,195,2,28,248,22,177,6,195,248,22,189, -13,195,194,27,248,22,152,7,23,195,1,249,22,190,13,248,22,190,7,250,22, -180,14,0,6,35,114,120,34,47,34,28,249,22,172,14,0,22,35,114,120,34, +32,115,116,114,105,110,103,23,197,2,28,28,248,22,183,13,23,195,2,249,22, +185,8,248,22,184,13,23,197,2,2,21,249,22,185,8,247,22,134,8,2,21, +27,28,248,22,178,6,23,196,2,23,195,2,248,22,188,7,248,22,187,13,23, +197,2,28,249,22,173,14,0,21,35,114,120,34,94,91,92,92,93,91,92,92, +93,91,63,93,91,92,92,93,34,23,195,2,28,248,22,178,6,195,248,22,190, +13,195,194,27,248,22,153,7,23,195,1,249,22,191,13,248,22,191,7,250,22, +181,14,0,6,35,114,120,34,47,34,28,249,22,173,14,0,22,35,114,120,34, 91,47,92,92,93,91,46,32,93,43,91,47,92,92,93,42,36,34,23,201,2, -23,199,1,250,22,180,14,0,19,35,114,120,34,91,32,46,93,43,40,91,47, +23,199,1,250,22,181,14,0,19,35,114,120,34,91,32,46,93,43,40,91,47, 92,92,93,42,41,36,34,23,202,1,6,2,2,92,49,80,159,44,37,38,2, -21,28,248,22,177,6,194,248,22,189,13,194,193,87,94,28,28,248,22,181,13, -23,195,2,10,28,248,22,177,6,23,195,2,28,248,22,139,14,23,195,2,10, -248,22,140,14,23,195,2,11,12,250,22,154,9,23,196,2,2,22,23,197,2, -28,248,22,139,14,23,195,2,12,248,22,133,12,249,22,139,11,248,22,142,7, -250,22,161,7,2,23,23,200,1,23,201,1,247,22,23,87,94,28,28,248,22, -181,13,23,195,2,10,28,248,22,177,6,23,195,2,28,248,22,139,14,23,195, -2,10,248,22,140,14,23,195,2,11,12,250,22,154,9,23,196,2,2,22,23, -197,2,28,248,22,139,14,23,195,2,12,248,22,133,12,249,22,139,11,248,22, -142,7,250,22,161,7,2,23,23,200,1,23,201,1,247,22,23,87,94,87,94, -28,28,248,22,181,13,23,195,2,10,28,248,22,177,6,23,195,2,28,248,22, -139,14,23,195,2,10,248,22,140,14,23,195,2,11,12,250,22,154,9,195,2, -22,23,197,2,28,248,22,139,14,23,195,2,12,248,22,133,12,249,22,139,11, -248,22,142,7,250,22,161,7,2,23,199,23,201,1,247,22,23,249,22,3,89, -162,8,44,37,50,9,223,2,33,35,196,87,94,28,28,248,22,181,13,23,194, -2,10,28,248,22,177,6,23,194,2,28,248,22,139,14,23,194,2,10,248,22, -140,14,23,194,2,11,12,250,22,154,9,2,7,2,22,23,196,2,28,248,22, -139,14,23,194,2,12,248,22,133,12,249,22,139,11,248,22,142,7,250,22,161, +21,28,248,22,178,6,194,248,22,190,13,194,193,87,94,28,28,248,22,182,13, +23,195,2,10,28,248,22,178,6,23,195,2,28,248,22,140,14,23,195,2,10, +248,22,141,14,23,195,2,11,12,250,22,155,9,23,196,2,2,22,23,197,2, +28,248,22,140,14,23,195,2,12,248,22,134,12,249,22,140,11,248,22,143,7, +250,22,162,7,2,23,23,200,1,23,201,1,247,22,23,87,94,28,28,248,22, +182,13,23,195,2,10,28,248,22,178,6,23,195,2,28,248,22,140,14,23,195, +2,10,248,22,141,14,23,195,2,11,12,250,22,155,9,23,196,2,2,22,23, +197,2,28,248,22,140,14,23,195,2,12,248,22,134,12,249,22,140,11,248,22, +143,7,250,22,162,7,2,23,23,200,1,23,201,1,247,22,23,87,94,87,94, +28,28,248,22,182,13,23,195,2,10,28,248,22,178,6,23,195,2,28,248,22, +140,14,23,195,2,10,248,22,141,14,23,195,2,11,12,250,22,155,9,195,2, +22,23,197,2,28,248,22,140,14,23,195,2,12,248,22,134,12,249,22,140,11, +248,22,143,7,250,22,162,7,2,23,199,23,201,1,247,22,23,249,22,3,89, +162,8,44,37,50,9,223,2,33,35,196,87,94,28,28,248,22,182,13,23,194, +2,10,28,248,22,178,6,23,194,2,28,248,22,140,14,23,194,2,10,248,22, +141,14,23,194,2,11,12,250,22,155,9,2,7,2,22,23,196,2,28,248,22, +140,14,23,194,2,12,248,22,134,12,249,22,140,11,248,22,143,7,250,22,162, 7,2,23,2,7,23,200,1,247,22,23,32,38,89,162,8,44,40,55,2,24, -222,33,39,28,248,22,79,23,197,2,87,94,23,196,1,248,22,133,12,249,22, -172,11,251,22,161,7,2,25,2,7,28,248,22,79,23,203,2,87,94,23,202, -1,23,201,1,250,22,1,22,135,14,23,204,1,23,205,1,23,200,1,247,22, -23,27,249,22,135,14,248,22,72,23,200,2,23,197,2,28,248,22,130,14,23, -194,2,27,250,22,1,22,135,14,23,197,1,199,28,248,22,130,14,193,192,251, +222,33,39,28,248,22,79,23,197,2,87,94,23,196,1,248,22,134,12,249,22, +173,11,251,22,162,7,2,25,2,7,28,248,22,79,23,203,2,87,94,23,202, +1,23,201,1,250,22,1,22,136,14,23,204,1,23,205,1,23,200,1,247,22, +23,27,249,22,136,14,248,22,72,23,200,2,23,197,2,28,248,22,131,14,23, +194,2,27,250,22,1,22,136,14,23,197,1,199,28,248,22,131,14,193,192,251, 2,38,198,199,200,248,22,73,202,251,2,38,197,198,199,248,22,73,201,87,94, -87,94,87,94,28,28,248,22,181,13,193,10,28,248,22,177,6,193,28,248,22, -139,14,193,10,248,22,140,14,193,11,12,250,22,154,9,2,7,2,22,195,28, -248,22,139,14,193,12,248,22,133,12,249,22,139,11,248,22,142,7,250,22,161, +87,94,87,94,28,28,248,22,182,13,193,10,28,248,22,178,6,193,28,248,22, +140,14,193,10,248,22,141,14,193,11,12,250,22,155,9,2,7,2,22,195,28, +248,22,140,14,193,12,248,22,134,12,249,22,140,11,248,22,143,7,250,22,162, 7,2,23,2,7,199,247,22,23,249,22,3,32,0,89,162,8,44,37,49,9, -222,33,37,195,27,247,22,159,14,251,2,38,196,197,198,196,32,41,89,162,44, +222,33,37,195,27,247,22,160,14,251,2,38,196,197,198,196,32,41,89,162,44, 42,59,2,24,222,33,42,28,248,22,79,23,199,2,87,94,23,198,1,248,23, -196,1,251,22,161,7,2,25,23,199,1,28,248,22,79,23,203,2,87,94,23, -202,1,23,201,1,250,22,1,22,135,14,23,204,1,23,205,1,23,198,1,27, -249,22,135,14,248,22,72,23,202,2,23,199,2,28,248,22,130,14,23,194,2, -27,250,22,1,22,135,14,23,197,1,23,202,2,28,248,22,130,14,23,194,2, +196,1,251,22,162,7,2,25,23,199,1,28,248,22,79,23,203,2,87,94,23, +202,1,23,201,1,250,22,1,22,136,14,23,204,1,23,205,1,23,198,1,27, +249,22,136,14,248,22,72,23,202,2,23,199,2,28,248,22,131,14,23,194,2, +27,250,22,1,22,136,14,23,197,1,23,202,2,28,248,22,131,14,23,194,2, 192,87,94,23,193,1,27,248,22,73,23,202,1,28,248,22,79,23,194,2,87, -94,23,193,1,248,23,199,1,251,22,161,7,2,25,23,202,1,28,248,22,79, -23,206,2,87,94,23,205,1,23,204,1,250,22,1,22,135,14,23,207,1,23, -208,1,23,201,1,27,249,22,135,14,248,22,72,23,197,2,23,202,2,28,248, -22,130,14,23,194,2,27,250,22,1,22,135,14,23,197,1,204,28,248,22,130, +94,23,193,1,248,23,199,1,251,22,162,7,2,25,23,202,1,28,248,22,79, +23,206,2,87,94,23,205,1,23,204,1,250,22,1,22,136,14,23,207,1,23, +208,1,23,201,1,27,249,22,136,14,248,22,72,23,197,2,23,202,2,28,248, +22,131,14,23,194,2,27,250,22,1,22,136,14,23,197,1,204,28,248,22,131, 14,193,192,253,2,41,203,204,205,206,23,15,248,22,73,201,253,2,41,202,203, 204,205,206,248,22,73,200,87,94,23,193,1,27,248,22,73,23,201,1,28,248, -22,79,23,194,2,87,94,23,193,1,248,23,198,1,251,22,161,7,2,25,23, +22,79,23,194,2,87,94,23,193,1,248,23,198,1,251,22,162,7,2,25,23, 201,1,28,248,22,79,23,205,2,87,94,23,204,1,23,203,1,250,22,1,22, -135,14,23,206,1,23,207,1,23,200,1,27,249,22,135,14,248,22,72,23,197, -2,23,201,2,28,248,22,130,14,23,194,2,27,250,22,1,22,135,14,23,197, -1,203,28,248,22,130,14,193,192,253,2,41,202,203,204,205,206,248,22,73,201, -253,2,41,201,202,203,204,205,248,22,73,200,27,247,22,159,14,253,2,41,198, -199,200,201,202,198,87,95,28,28,248,22,182,13,23,194,2,10,28,248,22,181, -13,23,194,2,10,28,248,22,177,6,23,194,2,28,248,22,139,14,23,194,2, -10,248,22,140,14,23,194,2,11,12,252,22,154,9,23,200,2,2,26,36,23, -198,2,23,199,2,28,28,248,22,177,6,23,195,2,10,248,22,166,7,23,195, -2,87,94,23,194,1,12,252,22,154,9,23,200,2,2,27,37,23,198,2,23, -199,1,91,159,39,11,90,161,39,36,11,248,22,138,14,23,197,2,87,94,23, -195,1,87,94,28,192,12,250,22,155,9,23,201,1,2,28,23,199,1,249,22, -7,194,195,91,159,38,11,90,161,38,36,11,87,95,28,28,248,22,182,13,23, -196,2,10,28,248,22,181,13,23,196,2,10,28,248,22,177,6,23,196,2,28, -248,22,139,14,23,196,2,10,248,22,140,14,23,196,2,11,12,252,22,154,9, -2,10,2,26,36,23,200,2,23,201,2,28,28,248,22,177,6,23,197,2,10, -248,22,166,7,23,197,2,12,252,22,154,9,2,10,2,27,37,23,200,2,23, -201,2,91,159,39,11,90,161,39,36,11,248,22,138,14,23,199,2,87,94,23, -195,1,87,94,28,192,12,250,22,155,9,2,10,2,28,23,201,2,249,22,7, -194,195,27,249,22,191,13,250,22,179,14,0,20,35,114,120,35,34,40,63,58, -91,46,93,91,94,46,93,42,124,41,36,34,248,22,187,13,23,201,1,28,248, -22,177,6,23,203,2,249,22,190,7,23,204,1,8,63,23,202,1,28,248,22, -182,13,23,199,2,248,22,183,13,23,199,1,87,94,23,198,1,247,22,184,13, -28,248,22,181,13,194,249,22,135,14,195,194,192,91,159,38,11,90,161,38,36, -11,87,95,28,28,248,22,182,13,23,196,2,10,28,248,22,181,13,23,196,2, -10,28,248,22,177,6,23,196,2,28,248,22,139,14,23,196,2,10,248,22,140, -14,23,196,2,11,12,252,22,154,9,2,11,2,26,36,23,200,2,23,201,2, -28,28,248,22,177,6,23,197,2,10,248,22,166,7,23,197,2,12,252,22,154, +136,14,23,206,1,23,207,1,23,200,1,27,249,22,136,14,248,22,72,23,197, +2,23,201,2,28,248,22,131,14,23,194,2,27,250,22,1,22,136,14,23,197, +1,203,28,248,22,131,14,193,192,253,2,41,202,203,204,205,206,248,22,73,201, +253,2,41,201,202,203,204,205,248,22,73,200,27,247,22,160,14,253,2,41,198, +199,200,201,202,198,87,95,28,28,248,22,183,13,23,194,2,10,28,248,22,182, +13,23,194,2,10,28,248,22,178,6,23,194,2,28,248,22,140,14,23,194,2, +10,248,22,141,14,23,194,2,11,12,252,22,155,9,23,200,2,2,26,36,23, +198,2,23,199,2,28,28,248,22,178,6,23,195,2,10,248,22,167,7,23,195, +2,87,94,23,194,1,12,252,22,155,9,23,200,2,2,27,37,23,198,2,23, +199,1,91,159,39,11,90,161,39,36,11,248,22,139,14,23,197,2,87,94,23, +195,1,87,94,28,192,12,250,22,156,9,23,201,1,2,28,23,199,1,249,22, +7,194,195,91,159,38,11,90,161,38,36,11,87,95,28,28,248,22,183,13,23, +196,2,10,28,248,22,182,13,23,196,2,10,28,248,22,178,6,23,196,2,28, +248,22,140,14,23,196,2,10,248,22,141,14,23,196,2,11,12,252,22,155,9, +2,10,2,26,36,23,200,2,23,201,2,28,28,248,22,178,6,23,197,2,10, +248,22,167,7,23,197,2,12,252,22,155,9,2,10,2,27,37,23,200,2,23, +201,2,91,159,39,11,90,161,39,36,11,248,22,139,14,23,199,2,87,94,23, +195,1,87,94,28,192,12,250,22,156,9,2,10,2,28,23,201,2,249,22,7, +194,195,27,249,22,128,14,250,22,180,14,0,20,35,114,120,35,34,40,63,58, +91,46,93,91,94,46,93,42,124,41,36,34,248,22,188,13,23,201,1,28,248, +22,178,6,23,203,2,249,22,191,7,23,204,1,8,63,23,202,1,28,248,22, +183,13,23,199,2,248,22,184,13,23,199,1,87,94,23,198,1,247,22,185,13, +28,248,22,182,13,194,249,22,136,14,195,194,192,91,159,38,11,90,161,38,36, +11,87,95,28,28,248,22,183,13,23,196,2,10,28,248,22,182,13,23,196,2, +10,28,248,22,178,6,23,196,2,28,248,22,140,14,23,196,2,10,248,22,141, +14,23,196,2,11,12,252,22,155,9,2,11,2,26,36,23,200,2,23,201,2, +28,28,248,22,178,6,23,197,2,10,248,22,167,7,23,197,2,12,252,22,155, 9,2,11,2,27,37,23,200,2,23,201,2,91,159,39,11,90,161,39,36,11, -248,22,138,14,23,199,2,87,94,23,195,1,87,94,28,192,12,250,22,155,9, -2,11,2,28,23,201,2,249,22,7,194,195,27,249,22,191,13,249,22,176,7, -250,22,180,14,0,9,35,114,120,35,34,91,46,93,34,248,22,187,13,23,203, -1,6,1,1,95,28,248,22,177,6,23,202,2,249,22,190,7,23,203,1,8, -63,23,201,1,28,248,22,182,13,23,199,2,248,22,183,13,23,199,1,87,94, -23,198,1,247,22,184,13,28,248,22,181,13,194,249,22,135,14,195,194,192,249, -247,22,144,5,194,11,249,80,159,38,47,37,9,9,249,80,159,38,47,37,195, -9,27,247,22,161,14,249,80,158,39,48,28,23,195,2,27,248,22,131,8,6, +248,22,139,14,23,199,2,87,94,23,195,1,87,94,28,192,12,250,22,156,9, +2,11,2,28,23,201,2,249,22,7,194,195,27,249,22,128,14,249,22,177,7, +250,22,181,14,0,9,35,114,120,35,34,91,46,93,34,248,22,188,13,23,203, +1,6,1,1,95,28,248,22,178,6,23,202,2,249,22,191,7,23,203,1,8, +63,23,201,1,28,248,22,183,13,23,199,2,248,22,184,13,23,199,1,87,94, +23,198,1,247,22,185,13,28,248,22,182,13,194,249,22,136,14,195,194,192,249, +247,22,145,5,194,11,249,80,159,38,47,37,9,9,249,80,159,38,47,37,195, +9,27,247,22,162,14,249,80,158,39,48,28,23,195,2,27,248,22,132,8,6, 11,11,80,76,84,67,79,76,76,69,67,84,83,28,192,192,6,0,0,6,0, -0,27,28,23,196,1,250,22,135,14,248,22,157,14,69,97,100,100,111,110,45, -100,105,114,247,22,129,8,6,8,8,99,111,108,108,101,99,116,115,11,27,248, -80,159,42,53,37,250,22,85,23,203,1,248,22,81,248,22,157,14,72,99,111, +0,27,28,23,196,1,250,22,136,14,248,22,158,14,69,97,100,100,111,110,45, +100,105,114,247,22,130,8,6,8,8,99,111,108,108,101,99,116,115,11,27,248, +80,159,42,53,37,250,22,85,23,203,1,248,22,81,248,22,158,14,72,99,111, 108,108,101,99,116,115,45,100,105,114,23,204,1,28,193,249,22,71,195,194,192, -32,51,89,162,8,44,39,8,31,2,19,222,33,52,27,249,22,168,14,23,197, +32,51,89,162,8,44,39,8,31,2,19,222,33,52,27,249,22,169,14,23,197, 2,23,198,2,28,23,193,2,87,94,23,196,1,27,248,22,96,23,195,2,27, -27,248,22,105,23,197,1,27,249,22,168,14,23,201,2,23,196,2,28,23,193, +27,248,22,105,23,197,1,27,249,22,169,14,23,201,2,23,196,2,28,23,193, 2,87,94,23,194,1,27,248,22,96,23,195,2,27,27,248,22,105,23,197,1, -27,249,22,168,14,23,205,2,23,196,2,28,23,193,2,87,94,23,194,1,27, -248,22,96,23,195,2,27,27,248,22,105,23,197,1,27,249,22,168,14,23,209, +27,249,22,169,14,23,205,2,23,196,2,28,23,193,2,87,94,23,194,1,27, +248,22,96,23,195,2,27,27,248,22,105,23,197,1,27,249,22,169,14,23,209, 2,23,196,2,28,23,193,2,87,94,23,194,1,27,248,22,96,23,195,2,27, -27,248,22,105,23,197,1,27,249,22,168,14,23,213,2,23,196,2,28,23,193, +27,248,22,105,23,197,1,27,249,22,169,14,23,213,2,23,196,2,28,23,193, 2,87,94,23,194,1,27,248,22,96,23,195,2,27,250,2,51,23,215,2,23, -216,1,248,22,105,23,199,1,28,249,22,172,7,23,196,2,2,29,249,22,85, -23,214,2,194,249,22,71,248,22,190,13,23,197,1,194,87,95,23,211,1,23, -193,1,28,249,22,172,7,23,196,2,2,29,249,22,85,23,212,2,9,249,22, -71,248,22,190,13,23,197,1,9,28,249,22,172,7,23,196,2,2,29,249,22, -85,23,210,2,194,249,22,71,248,22,190,13,23,197,1,194,87,94,23,193,1, -28,249,22,172,7,23,196,2,2,29,249,22,85,23,208,2,9,249,22,71,248, -22,190,13,23,197,1,9,28,249,22,172,7,23,196,2,2,29,249,22,85,23, -206,2,194,249,22,71,248,22,190,13,23,197,1,194,87,94,23,193,1,28,249, -22,172,7,23,196,2,2,29,249,22,85,23,204,2,9,249,22,71,248,22,190, -13,23,197,1,9,28,249,22,172,7,23,196,2,2,29,249,22,85,23,202,2, -194,249,22,71,248,22,190,13,23,197,1,194,87,94,23,193,1,28,249,22,172, -7,23,196,2,2,29,249,22,85,23,200,2,9,249,22,71,248,22,190,13,23, -197,1,9,28,249,22,172,7,23,196,2,2,29,249,22,85,197,194,87,94,23, -196,1,249,22,71,248,22,190,13,23,197,1,194,87,94,23,193,1,28,249,22, -172,7,23,198,2,2,29,249,22,85,195,9,87,94,23,194,1,249,22,71,248, -22,190,13,23,199,1,9,87,95,28,28,248,22,166,7,194,10,248,22,177,6, -194,12,250,22,154,9,2,14,6,21,21,98,121,116,101,32,115,116,114,105,110, +216,1,248,22,105,23,199,1,28,249,22,173,7,23,196,2,2,29,249,22,85, +23,214,2,194,249,22,71,248,22,191,13,23,197,1,194,87,95,23,211,1,23, +193,1,28,249,22,173,7,23,196,2,2,29,249,22,85,23,212,2,9,249,22, +71,248,22,191,13,23,197,1,9,28,249,22,173,7,23,196,2,2,29,249,22, +85,23,210,2,194,249,22,71,248,22,191,13,23,197,1,194,87,94,23,193,1, +28,249,22,173,7,23,196,2,2,29,249,22,85,23,208,2,9,249,22,71,248, +22,191,13,23,197,1,9,28,249,22,173,7,23,196,2,2,29,249,22,85,23, +206,2,194,249,22,71,248,22,191,13,23,197,1,194,87,94,23,193,1,28,249, +22,173,7,23,196,2,2,29,249,22,85,23,204,2,9,249,22,71,248,22,191, +13,23,197,1,9,28,249,22,173,7,23,196,2,2,29,249,22,85,23,202,2, +194,249,22,71,248,22,191,13,23,197,1,194,87,94,23,193,1,28,249,22,173, +7,23,196,2,2,29,249,22,85,23,200,2,9,249,22,71,248,22,191,13,23, +197,1,9,28,249,22,173,7,23,196,2,2,29,249,22,85,197,194,87,94,23, +196,1,249,22,71,248,22,191,13,23,197,1,194,87,94,23,193,1,28,249,22, +173,7,23,198,2,2,29,249,22,85,195,9,87,94,23,194,1,249,22,71,248, +22,191,13,23,199,1,9,87,95,28,28,248,22,167,7,194,10,248,22,178,6, +194,12,250,22,155,9,2,14,6,21,21,98,121,116,101,32,115,116,114,105,110, 103,32,111,114,32,115,116,114,105,110,103,196,28,28,248,22,80,195,249,22,4, -22,181,13,196,11,12,250,22,154,9,2,14,6,13,13,108,105,115,116,32,111, -102,32,112,97,116,104,115,197,250,2,51,197,195,28,248,22,177,6,197,248,22, -189,7,197,196,32,54,89,162,8,44,39,53,70,102,111,117,110,100,45,101,120, +22,182,13,196,11,12,250,22,155,9,2,14,6,13,13,108,105,115,116,32,111, +102,32,112,97,116,104,115,197,250,2,51,197,195,28,248,22,178,6,197,248,22, +190,7,197,196,32,54,89,162,8,44,39,53,70,102,111,117,110,100,45,101,120, 101,99,222,33,57,32,55,89,162,8,44,40,58,64,110,101,120,116,222,33,56, -27,248,22,143,14,23,196,2,28,249,22,186,8,23,195,2,23,197,1,11,28, -248,22,139,14,23,194,2,27,249,22,135,14,23,197,1,23,196,1,28,23,197, -2,91,159,39,11,90,161,39,36,11,248,22,138,14,23,197,2,87,95,23,195, -1,23,194,1,27,28,23,202,2,27,248,22,143,14,23,199,2,28,249,22,186, -8,23,195,2,23,200,2,11,28,248,22,139,14,23,194,2,250,2,54,23,205, -2,23,206,2,249,22,135,14,23,200,2,23,198,1,250,2,54,23,205,2,23, -206,2,23,196,1,11,28,23,193,2,192,87,94,23,193,1,27,28,248,22,181, -13,23,196,2,27,249,22,135,14,23,198,2,23,205,2,28,28,248,22,130,14, -193,10,248,22,129,14,193,192,11,11,28,23,193,2,192,87,94,23,193,1,28, -23,203,2,11,27,248,22,143,14,23,200,2,28,249,22,186,8,23,195,2,23, -201,1,11,28,248,22,139,14,23,194,2,250,2,54,23,206,1,23,207,1,249, -22,135,14,23,201,1,23,198,1,250,2,54,205,206,195,192,87,94,23,194,1, -28,23,196,2,91,159,39,11,90,161,39,36,11,248,22,138,14,23,197,2,87, -95,23,195,1,23,194,1,27,28,23,201,2,27,248,22,143,14,23,199,2,28, -249,22,186,8,23,195,2,23,200,2,11,28,248,22,139,14,23,194,2,250,2, -54,23,204,2,23,205,2,249,22,135,14,23,200,2,23,198,1,250,2,54,23, +27,248,22,144,14,23,196,2,28,249,22,187,8,23,195,2,23,197,1,11,28, +248,22,140,14,23,194,2,27,249,22,136,14,23,197,1,23,196,1,28,23,197, +2,91,159,39,11,90,161,39,36,11,248,22,139,14,23,197,2,87,95,23,195, +1,23,194,1,27,28,23,202,2,27,248,22,144,14,23,199,2,28,249,22,187, +8,23,195,2,23,200,2,11,28,248,22,140,14,23,194,2,250,2,54,23,205, +2,23,206,2,249,22,136,14,23,200,2,23,198,1,250,2,54,23,205,2,23, +206,2,23,196,1,11,28,23,193,2,192,87,94,23,193,1,27,28,248,22,182, +13,23,196,2,27,249,22,136,14,23,198,2,23,205,2,28,28,248,22,131,14, +193,10,248,22,130,14,193,192,11,11,28,23,193,2,192,87,94,23,193,1,28, +23,203,2,11,27,248,22,144,14,23,200,2,28,249,22,187,8,23,195,2,23, +201,1,11,28,248,22,140,14,23,194,2,250,2,54,23,206,1,23,207,1,249, +22,136,14,23,201,1,23,198,1,250,2,54,205,206,195,192,87,94,23,194,1, +28,23,196,2,91,159,39,11,90,161,39,36,11,248,22,139,14,23,197,2,87, +95,23,195,1,23,194,1,27,28,23,201,2,27,248,22,144,14,23,199,2,28, +249,22,187,8,23,195,2,23,200,2,11,28,248,22,140,14,23,194,2,250,2, +54,23,204,2,23,205,2,249,22,136,14,23,200,2,23,198,1,250,2,54,23, 204,2,23,205,2,23,196,1,11,28,23,193,2,192,87,94,23,193,1,27,28, -248,22,181,13,23,196,2,27,249,22,135,14,23,198,2,23,204,2,28,28,248, -22,130,14,193,10,248,22,129,14,193,192,11,11,28,23,193,2,192,87,94,23, -193,1,28,23,202,2,11,27,248,22,143,14,23,200,2,28,249,22,186,8,23, -195,2,23,201,1,11,28,248,22,139,14,23,194,2,250,2,54,23,205,1,23, -206,1,249,22,135,14,23,201,1,23,198,1,250,2,54,204,205,195,192,28,23, -193,2,91,159,39,11,90,161,39,36,11,248,22,138,14,23,199,2,87,95,23, +248,22,182,13,23,196,2,27,249,22,136,14,23,198,2,23,204,2,28,28,248, +22,131,14,193,10,248,22,130,14,193,192,11,11,28,23,193,2,192,87,94,23, +193,1,28,23,202,2,11,27,248,22,144,14,23,200,2,28,249,22,187,8,23, +195,2,23,201,1,11,28,248,22,140,14,23,194,2,250,2,54,23,205,1,23, +206,1,249,22,136,14,23,201,1,23,198,1,250,2,54,204,205,195,192,28,23, +193,2,91,159,39,11,90,161,39,36,11,248,22,139,14,23,199,2,87,95,23, 195,1,23,194,1,27,28,23,198,2,251,2,55,23,198,2,23,203,2,23,201, -2,23,202,2,11,28,23,193,2,192,87,94,23,193,1,27,28,248,22,181,13, -195,27,249,22,135,14,197,200,28,28,248,22,130,14,193,10,248,22,129,14,193, +2,23,202,2,11,28,23,193,2,192,87,94,23,193,1,27,28,248,22,182,13, +195,27,249,22,136,14,197,200,28,28,248,22,131,14,193,10,248,22,130,14,193, 192,11,11,28,192,192,28,198,11,251,2,55,198,203,201,202,194,32,58,89,162, 8,44,40,8,31,2,19,222,33,59,28,248,22,79,23,197,2,11,27,248,22, -142,14,248,22,72,23,199,2,27,249,22,135,14,23,196,1,23,197,2,28,248, -22,129,14,23,194,2,250,2,54,198,199,195,87,94,23,193,1,27,248,22,73, -23,200,1,28,248,22,79,23,194,2,11,27,248,22,142,14,248,22,72,23,196, -2,27,249,22,135,14,23,196,1,23,200,2,28,248,22,129,14,23,194,2,250, +143,14,248,22,72,23,199,2,27,249,22,136,14,23,196,1,23,197,2,28,248, +22,130,14,23,194,2,250,2,54,198,199,195,87,94,23,193,1,27,248,22,73, +23,200,1,28,248,22,79,23,194,2,11,27,248,22,143,14,248,22,72,23,196, +2,27,249,22,136,14,23,196,1,23,200,2,28,248,22,130,14,23,194,2,250, 2,54,201,202,195,87,94,23,193,1,27,248,22,73,23,197,1,28,248,22,79, -23,194,2,11,27,248,22,142,14,248,22,72,23,196,2,27,249,22,135,14,23, -196,1,23,203,2,28,248,22,129,14,23,194,2,250,2,54,204,205,195,87,94, +23,194,2,11,27,248,22,143,14,248,22,72,23,196,2,27,249,22,136,14,23, +196,1,23,203,2,28,248,22,130,14,23,194,2,250,2,54,204,205,195,87,94, 23,193,1,27,248,22,73,23,197,1,28,248,22,79,23,194,2,11,27,248,22, -142,14,248,22,72,23,196,2,27,249,22,135,14,23,196,1,23,206,2,28,248, -22,129,14,23,194,2,250,2,54,23,15,23,16,195,87,94,23,193,1,27,248, -22,73,23,197,1,28,248,22,79,23,194,2,11,27,248,22,142,14,248,22,72, -23,196,2,27,249,22,135,14,23,196,1,23,209,2,28,248,22,129,14,23,194, +143,14,248,22,72,23,196,2,27,249,22,136,14,23,196,1,23,206,2,28,248, +22,130,14,23,194,2,250,2,54,23,15,23,16,195,87,94,23,193,1,27,248, +22,73,23,197,1,28,248,22,79,23,194,2,11,27,248,22,143,14,248,22,72, +23,196,2,27,249,22,136,14,23,196,1,23,209,2,28,248,22,130,14,23,194, 2,250,2,54,23,18,23,19,195,87,94,23,193,1,27,248,22,73,23,197,1, -28,248,22,79,23,194,2,11,27,248,22,142,14,248,22,72,195,27,249,22,135, -14,23,196,1,23,19,28,248,22,129,14,193,250,2,54,23,21,23,22,195,251, -2,58,23,21,23,22,23,23,248,22,73,199,87,95,28,28,248,22,181,13,23, -195,2,10,28,248,22,177,6,23,195,2,28,248,22,139,14,23,195,2,10,248, -22,140,14,23,195,2,11,12,250,22,154,9,2,15,6,25,25,112,97,116,104, +28,248,22,79,23,194,2,11,27,248,22,143,14,248,22,72,195,27,249,22,136, +14,23,196,1,23,19,28,248,22,130,14,193,250,2,54,23,21,23,22,195,251, +2,58,23,21,23,22,23,23,248,22,73,199,87,95,28,28,248,22,182,13,23, +195,2,10,28,248,22,178,6,23,195,2,28,248,22,140,14,23,195,2,10,248, +22,141,14,23,195,2,11,12,250,22,155,9,2,15,6,25,25,112,97,116,104, 32,111,114,32,115,116,114,105,110,103,32,40,115,97,110,115,32,110,117,108,41, -23,197,2,28,28,23,195,2,28,28,248,22,181,13,23,196,2,10,28,248,22, -177,6,23,196,2,28,248,22,139,14,23,196,2,10,248,22,140,14,23,196,2, -11,248,22,139,14,23,196,2,11,10,12,250,22,154,9,2,15,6,29,29,35, +23,197,2,28,28,23,195,2,28,28,248,22,182,13,23,196,2,10,28,248,22, +178,6,23,196,2,28,248,22,140,14,23,196,2,10,248,22,141,14,23,196,2, +11,248,22,140,14,23,196,2,11,10,12,250,22,155,9,2,15,6,29,29,35, 102,32,111,114,32,114,101,108,97,116,105,118,101,32,112,97,116,104,32,111,114, -32,115,116,114,105,110,103,23,198,2,28,28,248,22,139,14,23,195,2,91,159, -39,11,90,161,39,36,11,248,22,138,14,23,198,2,249,22,184,8,194,68,114, -101,108,97,116,105,118,101,11,27,248,22,131,8,6,4,4,80,65,84,72,27, -28,23,194,2,27,249,80,159,41,48,38,23,197,1,9,28,249,22,184,8,247, -22,133,8,2,21,249,22,71,248,22,190,13,5,1,46,194,192,87,94,23,194, -1,9,28,248,22,79,23,194,2,11,27,248,22,142,14,248,22,72,23,196,2, -27,249,22,135,14,23,196,1,23,200,2,28,248,22,129,14,23,194,2,250,2, +32,115,116,114,105,110,103,23,198,2,28,28,248,22,140,14,23,195,2,91,159, +39,11,90,161,39,36,11,248,22,139,14,23,198,2,249,22,185,8,194,68,114, +101,108,97,116,105,118,101,11,27,248,22,132,8,6,4,4,80,65,84,72,27, +28,23,194,2,27,249,80,159,41,48,38,23,197,1,9,28,249,22,185,8,247, +22,134,8,2,21,249,22,71,248,22,191,13,5,1,46,194,192,87,94,23,194, +1,9,28,248,22,79,23,194,2,11,27,248,22,143,14,248,22,72,23,196,2, +27,249,22,136,14,23,196,1,23,200,2,28,248,22,130,14,23,194,2,250,2, 54,201,202,195,87,94,23,193,1,27,248,22,73,23,197,1,28,248,22,79,23, -194,2,11,27,248,22,142,14,248,22,72,23,196,2,27,249,22,135,14,23,196, -1,23,203,2,28,248,22,129,14,23,194,2,250,2,54,204,205,195,87,94,23, -193,1,27,248,22,73,23,197,1,28,248,22,79,23,194,2,11,27,248,22,142, -14,248,22,72,195,27,249,22,135,14,23,196,1,205,28,248,22,129,14,193,250, +194,2,11,27,248,22,143,14,248,22,72,23,196,2,27,249,22,136,14,23,196, +1,23,203,2,28,248,22,130,14,23,194,2,250,2,54,204,205,195,87,94,23, +193,1,27,248,22,73,23,197,1,28,248,22,79,23,194,2,11,27,248,22,143, +14,248,22,72,195,27,249,22,136,14,23,196,1,205,28,248,22,130,14,193,250, 2,54,23,15,23,16,195,251,2,58,23,15,23,16,23,17,248,22,73,199,27, -248,22,142,14,23,196,1,28,248,22,129,14,193,250,2,54,198,199,195,11,250, +248,22,143,14,23,196,1,28,248,22,130,14,193,250,2,54,198,199,195,11,250, 80,159,39,49,37,196,197,11,250,80,159,39,49,37,196,11,11,87,94,249,22, -168,6,247,22,140,5,195,248,22,130,6,249,22,184,3,36,249,22,168,3,197, +169,6,247,22,141,5,195,248,22,131,6,249,22,184,3,36,249,22,168,3,197, 198,27,28,23,197,2,87,95,23,196,1,23,195,1,23,197,1,87,94,23,197, -1,27,248,22,157,14,2,20,27,249,80,159,41,49,37,23,196,1,11,27,27, +1,27,248,22,158,14,2,20,27,249,80,159,41,49,37,23,196,1,11,27,27, 248,22,187,3,23,200,1,28,192,192,36,27,27,248,22,187,3,23,202,1,28, -192,192,36,249,22,171,5,23,197,1,83,158,40,20,100,95,89,162,8,44,36, -48,9,224,3,2,33,63,23,195,1,23,196,1,27,248,22,156,5,23,195,1, +192,192,36,249,22,172,5,23,197,1,83,158,40,20,100,95,89,162,8,44,36, +48,9,224,3,2,33,63,23,195,1,23,196,1,27,248,22,157,5,23,195,1, 248,80,159,39,54,37,193,159,36,20,105,159,36,16,1,11,16,0,83,158,42, 20,103,145,2,1,2,1,29,11,11,11,11,11,10,43,80,158,36,36,20,105, 159,38,16,17,2,2,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2, @@ -375,7 +375,7 @@ 2,89,162,8,44,37,51,2,19,223,0,33,30,80,159,36,54,37,83,158,36, 16,2,89,162,8,44,37,56,2,19,223,0,33,31,80,159,36,53,37,83,158, 36,16,2,32,0,89,162,44,37,45,2,2,222,33,32,80,159,36,36,37,83, -158,36,16,2,249,22,179,6,7,92,7,92,80,159,36,37,37,83,158,36,16, +158,36,16,2,249,22,180,6,7,92,7,92,80,159,36,37,37,83,158,36,16, 2,89,162,44,37,54,2,4,223,0,33,33,80,159,36,38,37,83,158,36,16, 2,32,0,89,162,8,44,38,50,2,5,222,33,34,80,159,36,39,37,83,158, 36,16,2,32,0,89,162,8,44,39,51,2,6,222,33,36,80,159,36,40,37, @@ -388,8 +388,8 @@ 33,47,80,159,36,46,37,83,158,36,16,2,83,158,39,20,99,96,2,13,89, 162,44,36,44,9,223,0,33,48,89,162,44,37,45,9,223,0,33,49,89,162, 44,38,55,9,223,0,33,50,80,159,36,47,37,83,158,36,16,2,27,248,22, -164,14,248,22,189,7,27,28,249,22,184,8,247,22,133,8,2,21,6,1,1, -59,6,1,1,58,250,22,161,7,6,14,14,40,91,94,126,97,93,42,41,126, +165,14,248,22,190,7,27,28,249,22,185,8,247,22,134,8,2,21,6,1,1, +59,6,1,1,58,250,22,162,7,6,14,14,40,91,94,126,97,93,42,41,126, 97,40,46,42,41,23,196,2,23,196,1,89,162,8,44,38,48,2,14,223,0, 33,53,80,159,36,48,37,83,158,36,16,2,83,158,39,20,99,96,2,15,89, 162,8,44,39,8,24,9,223,0,33,60,89,162,44,38,47,9,223,0,33,61, @@ -400,7 +400,7 @@ EVAL_ONE_SIZED_STR((char *)expr, 6245); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,54,9,0,0,0,1,0,0,10,0,16,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,55,9,0,0,0,1,0,0,10,0,16,0, 29,0,44,0,58,0,72,0,86,0,128,0,0,0,57,1,0,0,69,35,37, 98,117,105,108,116,105,110,65,113,117,111,116,101,29,94,2,2,67,35,37,117, 116,105,108,115,11,29,94,2,2,69,35,37,110,101,116,119,111,114,107,11,29, @@ -420,7 +420,7 @@ EVAL_ONE_SIZED_STR((char *)expr, 352); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,54,74,0,0,0,1,0,0,7,0,18,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,48,46,48,46,55,74,0,0,0,1,0,0,7,0,18,0, 45,0,51,0,64,0,73,0,80,0,102,0,124,0,150,0,162,0,180,0,200, 0,212,0,228,0,251,0,7,1,38,1,45,1,50,1,55,1,60,1,65,1, 70,1,79,1,84,1,88,1,94,1,101,1,107,1,115,1,124,1,145,1,166, @@ -446,47 +446,47 @@ 109,101,5,3,46,122,111,5,3,46,122,111,6,6,6,110,97,116,105,118,101, 64,108,111,111,112,63,108,105,98,6,3,3,46,115,115,6,4,4,46,114,107, 116,5,4,46,114,107,116,67,105,103,110,111,114,101,100,249,22,14,195,80,159, -38,46,38,250,22,135,14,23,197,1,23,199,1,249,80,159,43,39,38,23,198, -1,2,23,250,22,135,14,23,197,1,23,199,1,249,80,159,43,39,38,23,198, -1,2,24,252,22,135,14,23,199,1,23,201,1,2,25,247,22,134,8,249,80, -159,45,39,38,23,200,1,80,159,45,36,38,252,22,135,14,23,199,1,23,201, -1,2,25,247,22,134,8,249,80,159,45,39,38,23,200,1,80,159,45,36,38, -27,252,22,135,14,23,200,1,23,202,1,2,25,247,22,134,8,249,80,159,46, -39,38,23,201,1,80,159,46,36,38,27,250,22,152,14,196,11,32,0,89,162, -8,44,36,41,9,222,11,28,192,249,22,71,195,194,11,27,252,22,135,14,23, -200,1,23,202,1,2,25,247,22,134,8,249,80,159,46,39,38,23,201,1,80, -159,46,36,38,27,250,22,152,14,196,11,32,0,89,162,8,44,36,41,9,222, -11,28,192,249,22,71,195,194,11,27,250,22,135,14,23,198,1,23,200,1,249, -80,159,44,39,38,23,199,1,2,23,27,250,22,152,14,196,11,32,0,89,162, -8,44,36,41,9,222,11,28,192,249,22,71,195,194,11,27,250,22,135,14,23, -198,1,23,200,1,249,80,159,44,39,38,23,199,1,2,24,27,250,22,152,14, +38,46,38,250,22,136,14,23,197,1,23,199,1,249,80,159,43,39,38,23,198, +1,2,23,250,22,136,14,23,197,1,23,199,1,249,80,159,43,39,38,23,198, +1,2,24,252,22,136,14,23,199,1,23,201,1,2,25,247,22,135,8,249,80, +159,45,39,38,23,200,1,80,159,45,36,38,252,22,136,14,23,199,1,23,201, +1,2,25,247,22,135,8,249,80,159,45,39,38,23,200,1,80,159,45,36,38, +27,252,22,136,14,23,200,1,23,202,1,2,25,247,22,135,8,249,80,159,46, +39,38,23,201,1,80,159,46,36,38,27,250,22,153,14,196,11,32,0,89,162, +8,44,36,41,9,222,11,28,192,249,22,71,195,194,11,27,252,22,136,14,23, +200,1,23,202,1,2,25,247,22,135,8,249,80,159,46,39,38,23,201,1,80, +159,46,36,38,27,250,22,153,14,196,11,32,0,89,162,8,44,36,41,9,222, +11,28,192,249,22,71,195,194,11,27,250,22,136,14,23,198,1,23,200,1,249, +80,159,44,39,38,23,199,1,2,23,27,250,22,153,14,196,11,32,0,89,162, +8,44,36,41,9,222,11,28,192,249,22,71,195,194,11,27,250,22,136,14,23, +198,1,23,200,1,249,80,159,44,39,38,23,199,1,2,24,27,250,22,153,14, 196,11,32,0,89,162,8,44,36,41,9,222,11,28,192,249,22,71,195,194,11, -87,94,28,248,80,159,37,38,38,23,195,2,12,250,22,154,9,77,108,111,97, +87,94,28,248,80,159,37,38,38,23,195,2,12,250,22,155,9,77,108,111,97, 100,47,117,115,101,45,99,111,109,112,105,108,101,100,6,25,25,112,97,116,104, 32,111,114,32,118,97,108,105,100,45,112,97,116,104,32,115,116,114,105,110,103, -23,197,2,91,159,46,11,90,161,37,36,11,28,248,22,141,14,23,205,2,23, -204,2,27,247,22,145,5,28,23,193,2,249,22,142,14,23,207,2,23,195,1, -23,205,2,90,161,39,37,11,248,22,138,14,23,205,1,87,94,23,196,1,90, -161,38,40,11,28,23,205,2,27,248,22,186,13,23,197,2,27,248,22,169,7, -23,195,2,28,28,249,22,180,3,23,195,2,40,249,22,172,7,5,4,46,114, -107,116,249,22,175,7,23,198,2,249,22,168,3,23,199,2,40,11,249,22,7, -23,199,2,248,22,190,13,249,22,176,7,250,22,175,7,23,202,1,36,249,22, +23,197,2,91,159,46,11,90,161,37,36,11,28,248,22,142,14,23,205,2,23, +204,2,27,247,22,146,5,28,23,193,2,249,22,143,14,23,207,2,23,195,1, +23,205,2,90,161,39,37,11,248,22,139,14,23,205,1,87,94,23,196,1,90, +161,38,40,11,28,23,205,2,27,248,22,187,13,23,197,2,27,248,22,170,7, +23,195,2,28,28,249,22,180,3,23,195,2,40,249,22,173,7,5,4,46,114, +107,116,249,22,176,7,23,198,2,249,22,168,3,23,199,2,40,11,249,22,7, +23,199,2,248,22,191,13,249,22,177,7,250,22,176,7,23,202,1,36,249,22, 168,3,23,203,1,40,5,3,46,115,115,249,22,7,23,199,2,11,249,22,7, -23,197,2,11,90,161,37,42,11,28,249,22,184,8,23,199,2,23,197,2,23, -193,2,249,22,135,14,23,196,2,23,199,2,90,161,37,43,11,28,23,198,2, -28,249,22,184,8,23,200,2,23,197,1,23,193,1,87,94,23,193,1,249,22, -135,14,23,196,2,23,200,2,87,94,23,195,1,11,90,161,37,44,11,28,249, -22,184,8,23,196,2,68,114,101,108,97,116,105,118,101,87,94,23,194,1,2, -22,23,194,1,90,161,37,45,11,247,22,160,14,27,27,250,22,152,14,23,204, +23,197,2,11,90,161,37,42,11,28,249,22,185,8,23,199,2,23,197,2,23, +193,2,249,22,136,14,23,196,2,23,199,2,90,161,37,43,11,28,23,198,2, +28,249,22,185,8,23,200,2,23,197,1,23,193,1,87,94,23,193,1,249,22, +136,14,23,196,2,23,200,2,87,94,23,195,1,11,90,161,37,44,11,28,249, +22,185,8,23,196,2,68,114,101,108,97,116,105,118,101,87,94,23,194,1,2, +22,23,194,1,90,161,37,45,11,247,22,161,14,27,27,250,22,153,14,23,204, 2,11,32,0,89,162,8,44,36,41,9,222,11,28,192,249,22,71,23,203,2, -194,11,27,28,23,202,2,28,23,194,2,11,27,250,22,152,14,23,206,2,11, +194,11,27,28,23,202,2,28,23,194,2,11,27,250,22,153,14,23,206,2,11, 32,0,89,162,8,44,36,41,9,222,11,28,192,249,22,71,23,205,2,194,11, 11,27,28,23,195,2,23,195,2,23,194,2,27,89,162,44,37,50,62,122,111, 225,14,12,8,33,33,27,89,162,44,37,50,66,97,108,116,45,122,111,225,15, 13,10,33,34,27,89,162,44,37,52,9,225,16,14,10,33,35,27,89,162,44, -37,52,9,225,17,15,12,33,36,27,28,23,200,2,23,200,2,248,22,182,8, +37,52,9,225,17,15,12,33,36,27,28,23,200,2,23,200,2,248,22,183,8, 23,200,2,27,28,23,207,2,28,23,200,2,87,94,23,201,1,23,200,2,248, -22,182,8,23,202,1,11,27,28,23,195,2,28,23,197,1,27,249,22,5,89, +22,183,8,23,202,1,11,27,28,23,195,2,28,23,197,1,27,249,22,5,89, 162,8,44,37,53,9,225,23,21,17,33,37,23,215,2,27,28,23,202,2,11, 193,28,192,192,28,193,28,23,202,2,28,249,22,180,3,248,22,73,196,248,22, 73,23,205,2,193,11,11,11,11,87,94,23,197,1,11,28,23,193,2,87,105, @@ -494,8 +494,8 @@ 23,199,1,23,198,1,23,196,1,23,195,1,23,194,1,20,14,159,80,159,56, 40,38,250,80,159,59,41,38,249,22,27,11,80,159,8,25,40,38,22,168,4, 11,20,14,159,80,159,56,40,38,250,80,159,59,41,38,249,22,27,11,80,159, -8,25,40,38,22,145,5,28,248,22,181,13,23,215,2,23,214,1,87,94,23, -214,1,247,22,158,14,249,247,22,163,14,248,22,72,195,23,24,87,94,23,193, +8,25,40,38,22,146,5,28,248,22,182,13,23,215,2,23,214,1,87,94,23, +214,1,247,22,159,14,249,247,22,164,14,248,22,72,195,23,24,87,94,23,193, 1,27,28,23,195,2,28,23,197,1,27,249,22,5,89,162,8,44,37,53,9, 225,24,22,19,33,38,23,216,2,27,28,23,204,2,11,193,28,192,192,28,193, 28,203,28,249,22,180,3,248,22,73,196,248,22,73,206,193,11,11,11,11,87, @@ -503,8 +503,8 @@ 208,1,23,201,1,23,200,1,23,199,1,23,196,1,23,195,1,20,14,159,80, 159,57,40,38,250,80,159,8,24,41,38,249,22,27,11,80,159,8,26,40,38, 22,168,4,23,214,1,20,14,159,80,159,57,40,38,250,80,159,8,24,41,38, -249,22,27,11,80,159,8,26,40,38,22,145,5,28,248,22,181,13,23,216,2, -23,215,1,87,94,23,215,1,247,22,158,14,249,247,22,163,14,248,22,72,195, +249,22,27,11,80,159,8,26,40,38,22,146,5,28,248,22,182,13,23,216,2, +23,215,1,87,94,23,215,1,247,22,159,14,249,247,22,164,14,248,22,72,195, 23,25,87,94,23,193,1,27,28,23,197,2,28,23,201,1,27,249,22,5,83, 158,40,20,100,94,89,162,8,44,37,51,9,225,25,23,19,33,39,23,212,1, 23,217,2,27,28,23,204,2,11,193,28,192,192,28,193,28,23,204,2,28,249, @@ -513,8 +513,8 @@ 211,1,23,210,1,23,202,1,23,200,1,23,197,1,23,196,1,20,14,159,80, 159,58,40,38,250,80,159,8,25,41,38,249,22,27,11,80,159,8,27,40,38, 22,168,4,11,20,14,159,80,159,58,40,38,250,80,159,8,25,41,38,249,22, -27,11,80,159,8,27,40,38,22,145,5,28,248,22,181,13,23,217,2,23,216, -1,87,94,23,216,1,247,22,158,14,249,247,22,143,5,248,22,72,195,23,26, +27,11,80,159,8,27,40,38,22,146,5,28,248,22,182,13,23,217,2,23,216, +1,87,94,23,216,1,247,22,159,14,249,247,22,144,5,248,22,72,195,23,26, 87,94,23,193,1,27,28,23,197,1,28,23,201,1,27,249,22,5,83,158,40, 20,100,94,89,162,8,44,37,51,9,225,26,24,21,33,40,23,214,1,23,218, 1,27,28,23,205,2,11,193,28,192,192,28,193,28,204,28,249,22,180,3,248, @@ -522,21 +522,21 @@ 87,94,23,201,1,11,28,23,193,2,87,95,23,212,1,23,198,1,20,14,159, 80,159,59,40,38,250,80,159,8,26,41,38,249,22,27,11,80,159,8,28,40, 38,22,168,4,23,216,1,20,14,159,80,159,59,40,38,250,80,159,8,26,41, -38,249,22,27,11,80,159,8,28,40,38,22,145,5,28,248,22,181,13,23,218, -2,23,217,1,87,94,23,217,1,247,22,158,14,249,247,22,143,5,248,22,72, +38,249,22,27,11,80,159,8,28,40,38,22,146,5,28,248,22,182,13,23,218, +2,23,217,1,87,94,23,217,1,247,22,159,14,249,247,22,144,5,248,22,72, 195,23,27,87,94,23,193,1,27,28,23,199,2,87,94,23,214,1,23,213,1, 87,94,23,213,1,23,214,1,20,14,159,80,159,8,24,40,38,250,80,159,8, 27,41,38,249,22,27,11,80,159,8,29,40,38,22,168,4,28,23,29,28,23, 202,1,11,195,87,94,23,202,1,11,20,14,159,80,159,8,24,40,38,250,80, -159,8,27,41,38,249,22,27,11,80,159,8,29,40,38,22,145,5,28,248,22, -181,13,23,219,2,23,218,1,87,94,23,218,1,247,22,158,14,249,247,22,143, +159,8,27,41,38,249,22,27,11,80,159,8,29,40,38,22,146,5,28,248,22, +182,13,23,219,2,23,218,1,87,94,23,218,1,247,22,159,14,249,247,22,144, 5,194,23,28,0,17,35,114,120,34,94,40,46,42,63,41,47,40,46,42,41, -36,34,32,43,89,162,8,44,37,59,2,26,222,33,44,27,249,22,168,14,2, +36,34,32,43,89,162,8,44,37,59,2,26,222,33,44,27,249,22,169,14,2, 42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196, -2,27,248,22,105,23,197,1,27,249,22,168,14,2,42,23,196,2,28,23,193, +2,27,248,22,105,23,197,1,27,249,22,169,14,2,42,23,196,2,28,23,193, 2,87,94,23,194,1,249,22,71,248,22,96,23,196,2,27,248,22,105,23,197, -1,27,249,22,168,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249, -22,71,248,22,96,23,196,2,27,248,22,105,23,197,1,27,249,22,168,14,2, +1,27,249,22,169,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249, +22,71,248,22,96,23,196,2,27,248,22,105,23,197,1,27,249,22,169,14,2, 42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196, 2,248,2,43,248,22,105,23,197,1,248,22,81,194,248,22,81,194,248,22,81, 194,248,22,81,194,32,45,89,162,44,37,55,2,26,222,33,46,28,248,22,79, @@ -546,12 +546,12 @@ 79,248,22,73,23,195,2,249,22,7,9,248,22,72,195,91,159,38,11,90,161, 38,36,11,248,2,45,248,22,73,196,249,22,7,249,22,71,248,22,72,199,196, 195,249,22,7,249,22,71,248,22,72,199,196,195,249,22,7,249,22,71,248,22, -72,199,196,195,27,27,249,22,168,14,2,42,23,197,2,28,23,193,2,87,94, +72,199,196,195,27,27,249,22,169,14,2,42,23,197,2,28,23,193,2,87,94, 23,195,1,249,22,71,248,22,96,23,196,2,27,248,22,105,23,197,1,27,249, -22,168,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248, -22,96,23,196,2,27,248,22,105,23,197,1,27,249,22,168,14,2,42,23,196, +22,169,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248, +22,96,23,196,2,27,248,22,105,23,197,1,27,249,22,169,14,2,42,23,196, 2,28,23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196,2,27,248, -22,105,23,197,1,27,249,22,168,14,2,42,23,196,2,28,23,193,2,87,94, +22,105,23,197,1,27,249,22,169,14,2,42,23,196,2,28,23,193,2,87,94, 23,194,1,249,22,71,248,22,96,23,196,2,248,2,43,248,22,105,23,197,1, 248,22,81,194,248,22,81,194,248,22,81,194,248,22,81,195,28,23,195,1,192, 28,248,22,79,248,22,73,23,195,2,249,22,7,9,248,22,72,195,91,159,38, @@ -560,69 +560,69 @@ 196,28,248,22,79,248,22,73,23,195,2,249,22,7,9,248,22,72,195,91,159, 38,11,90,161,38,36,11,248,2,45,248,22,73,196,249,22,7,249,22,71,248, 22,72,199,196,195,249,22,7,249,22,71,248,22,72,199,196,195,249,22,7,249, -22,71,248,22,72,199,196,195,87,95,28,248,22,186,4,195,12,250,22,154,9, +22,71,248,22,72,199,196,195,87,95,28,248,22,186,4,195,12,250,22,155,9, 2,18,6,20,20,114,101,115,111,108,118,101,100,45,109,111,100,117,108,101,45, 112,97,116,104,197,28,24,193,2,248,24,194,1,195,87,94,23,193,1,12,27, -27,250,22,150,2,80,159,42,43,38,248,22,129,15,247,22,161,12,11,28,23, +27,250,22,150,2,80,159,42,43,38,248,22,130,15,247,22,162,12,11,28,23, 193,2,192,87,94,23,193,1,27,247,22,130,2,87,94,250,22,148,2,80,159, -43,43,38,248,22,129,15,247,22,161,12,195,192,250,22,148,2,195,198,66,97, -116,116,97,99,104,251,211,197,198,199,10,28,192,250,22,153,9,11,196,195,248, -22,151,9,194,32,51,89,162,44,37,52,2,26,222,33,52,28,248,22,79,248, +43,43,38,248,22,130,15,247,22,162,12,195,192,250,22,148,2,195,198,66,97, +116,116,97,99,104,251,211,197,198,199,10,28,192,250,22,154,9,11,196,195,248, +22,152,9,194,32,51,89,162,44,37,52,2,26,222,33,52,28,248,22,79,248, 22,73,23,195,2,249,22,7,9,248,22,72,195,91,159,38,11,90,161,38,36, 11,27,248,22,73,196,28,248,22,79,248,22,73,23,195,2,249,22,7,9,248, 22,72,195,91,159,38,11,90,161,38,36,11,248,2,51,248,22,73,196,249,22, 7,249,22,71,248,22,72,199,196,195,249,22,7,249,22,71,248,22,72,199,196, -195,32,53,89,162,8,44,37,55,2,26,222,33,54,27,249,22,168,14,2,42, +195,32,53,89,162,8,44,37,55,2,26,222,33,54,27,249,22,169,14,2,42, 23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196,2, -27,248,22,105,23,197,1,27,249,22,168,14,2,42,23,196,2,28,23,193,2, +27,248,22,105,23,197,1,27,249,22,169,14,2,42,23,196,2,28,23,193,2, 87,94,23,194,1,249,22,71,248,22,96,23,196,2,27,248,22,105,23,197,1, -27,249,22,168,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22, +27,249,22,169,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22, 71,248,22,96,23,196,2,248,2,53,248,22,105,23,197,1,248,22,81,194,248, 22,81,194,248,22,81,194,32,55,89,162,44,37,52,2,26,222,33,56,28,248, 22,79,248,22,73,23,195,2,249,22,7,9,248,22,72,195,91,159,38,11,90, 161,38,36,11,27,248,22,73,196,28,248,22,79,248,22,73,23,195,2,249,22, 7,9,248,22,72,195,91,159,38,11,90,161,38,36,11,248,2,55,248,22,73, 196,249,22,7,249,22,71,248,22,72,199,196,195,249,22,7,249,22,71,248,22, -72,199,196,195,32,57,89,162,8,44,37,55,2,26,222,33,58,27,249,22,168, +72,199,196,195,32,57,89,162,8,44,37,55,2,26,222,33,58,27,249,22,169, 14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22,96, -23,196,2,27,248,22,105,23,197,1,27,249,22,168,14,2,42,23,196,2,28, +23,196,2,27,248,22,105,23,197,1,27,249,22,169,14,2,42,23,196,2,28, 23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196,2,27,248,22,105, -23,197,1,27,249,22,168,14,2,42,23,196,2,28,23,193,2,87,94,23,194, +23,197,1,27,249,22,169,14,2,42,23,196,2,28,23,193,2,87,94,23,194, 1,249,22,71,248,22,96,23,196,2,248,2,57,248,22,105,23,197,1,248,22, -81,194,248,22,81,194,248,22,81,194,28,249,22,183,6,194,6,1,1,46,2, -22,28,249,22,183,6,194,6,2,2,46,46,62,117,112,192,0,11,35,114,120, +81,194,248,22,81,194,248,22,81,194,28,249,22,184,6,194,6,1,1,46,2, +22,28,249,22,184,6,194,6,2,2,46,46,62,117,112,192,0,11,35,114,120, 34,91,46,93,115,115,36,34,32,61,89,162,44,37,52,2,26,222,33,62,28, 248,22,79,248,22,73,23,195,2,249,22,7,9,248,22,72,195,91,159,38,11, 90,161,38,36,11,27,248,22,73,196,28,248,22,79,248,22,73,23,195,2,249, 22,7,9,248,22,72,195,91,159,38,11,90,161,38,36,11,248,2,61,248,22, 73,196,249,22,7,249,22,71,248,22,72,199,196,195,249,22,7,249,22,71,248, 22,72,199,196,195,32,63,89,162,8,44,37,55,2,26,222,33,64,27,249,22, -168,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22, -96,23,196,2,27,248,22,105,23,197,1,27,249,22,168,14,2,42,23,196,2, +169,14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22, +96,23,196,2,27,248,22,105,23,197,1,27,249,22,169,14,2,42,23,196,2, 28,23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196,2,27,248,22, -105,23,197,1,27,249,22,168,14,2,42,23,196,2,28,23,193,2,87,94,23, +105,23,197,1,27,249,22,169,14,2,42,23,196,2,28,23,193,2,87,94,23, 194,1,249,22,71,248,22,96,23,196,2,248,2,63,248,22,105,23,197,1,248, 22,81,194,248,22,81,194,248,22,81,194,32,65,89,162,8,44,37,55,2,26, -222,33,66,27,249,22,168,14,2,42,23,196,2,28,23,193,2,87,94,23,194, -1,249,22,71,248,22,96,23,196,2,27,248,22,105,23,197,1,27,249,22,168, +222,33,66,27,249,22,169,14,2,42,23,196,2,28,23,193,2,87,94,23,194, +1,249,22,71,248,22,96,23,196,2,27,248,22,105,23,197,1,27,249,22,169, 14,2,42,23,196,2,28,23,193,2,87,94,23,194,1,249,22,71,248,22,96, -23,196,2,27,248,22,105,23,197,1,27,249,22,168,14,2,42,23,196,2,28, +23,196,2,27,248,22,105,23,197,1,27,249,22,169,14,2,42,23,196,2,28, 23,193,2,87,94,23,194,1,249,22,71,248,22,96,23,196,2,248,2,65,248, 22,105,23,197,1,248,22,81,194,248,22,81,194,248,22,81,194,27,248,2,65, -23,195,1,192,28,249,22,186,8,248,22,73,23,200,2,23,197,1,28,249,22, -184,8,248,22,72,23,200,2,23,196,1,251,22,151,9,2,18,6,26,26,99, +23,195,1,192,28,249,22,187,8,248,22,73,23,200,2,23,197,1,28,249,22, +185,8,248,22,72,23,200,2,23,196,1,251,22,152,9,2,18,6,26,26,99, 121,99,108,101,32,105,110,32,108,111,97,100,105,110,103,32,97,116,32,126,101, 58,32,126,101,23,200,1,249,22,2,22,73,248,22,86,249,22,71,23,206,1, -23,202,1,12,12,247,192,20,14,159,80,159,40,45,38,249,22,71,248,22,129, -15,247,22,161,12,23,197,1,20,14,159,80,159,40,40,38,250,80,159,43,41, -38,249,22,27,11,80,159,45,40,38,22,167,4,23,196,1,249,247,22,144,5, -23,198,1,248,22,59,248,22,185,13,23,198,1,87,94,28,28,248,22,181,13, -23,196,2,10,248,22,130,5,23,196,2,12,28,23,197,2,250,22,153,9,11, +23,202,1,12,12,247,192,20,14,159,80,159,40,45,38,249,22,71,248,22,130, +15,247,22,162,12,23,197,1,20,14,159,80,159,40,40,38,250,80,159,43,41, +38,249,22,27,11,80,159,45,40,38,22,167,4,23,196,1,249,247,22,145,5, +23,198,1,248,22,59,248,22,186,13,23,198,1,87,94,28,28,248,22,182,13, +23,196,2,10,248,22,130,5,23,196,2,12,28,23,197,2,250,22,154,9,11, 6,15,15,98,97,100,32,109,111,100,117,108,101,32,112,97,116,104,23,200,2, -250,22,154,9,2,18,6,19,19,109,111,100,117,108,101,45,112,97,116,104,32, -111,114,32,112,97,116,104,23,198,2,28,28,248,22,69,23,196,2,249,22,184, +250,22,155,9,2,18,6,19,19,109,111,100,117,108,101,45,112,97,116,104,32, +111,114,32,112,97,116,104,23,198,2,28,28,248,22,69,23,196,2,249,22,185, 8,248,22,72,23,198,2,2,4,11,248,22,187,4,248,22,96,196,28,28,248, -22,69,23,196,2,249,22,184,8,248,22,72,23,198,2,66,112,108,97,110,101, +22,69,23,196,2,249,22,185,8,248,22,72,23,198,2,66,112,108,97,110,101, 116,11,87,94,28,207,12,20,14,159,80,159,37,52,38,80,158,37,50,90,161, 37,36,10,249,22,169,4,21,94,2,27,6,19,19,112,108,97,110,101,116,47, 114,101,115,111,108,118,101,114,46,114,107,116,1,27,112,108,97,110,101,116,45, @@ -630,93 +630,93 @@ 252,212,199,200,201,202,80,158,42,50,87,94,23,193,1,27,89,162,8,44,37, 46,79,115,104,111,119,45,99,111,108,108,101,99,116,105,111,110,45,101,114,114, 223,5,33,50,27,28,248,22,56,23,198,2,27,250,22,150,2,80,159,43,44, -38,249,22,71,23,203,2,247,22,159,14,11,28,23,193,2,192,87,94,23,193, +38,249,22,71,23,203,2,247,22,160,14,11,28,23,193,2,192,87,94,23,193, 1,91,159,38,11,90,161,38,36,11,27,248,22,62,23,202,2,248,2,51,248, 2,53,23,195,1,27,251,80,159,47,54,38,2,18,23,202,1,28,248,22,79, 23,199,2,23,199,2,248,22,72,23,199,2,28,248,22,79,23,199,2,9,248, -22,73,23,199,2,249,22,135,14,23,195,1,28,248,22,79,23,197,1,87,94, -23,197,1,6,8,8,109,97,105,110,46,114,107,116,249,22,136,7,23,199,1, -6,4,4,46,114,107,116,28,248,22,177,6,23,198,2,87,94,23,194,1,27, -27,28,23,200,2,28,249,22,184,8,23,202,2,80,158,43,47,80,158,41,48, -27,248,22,188,4,23,202,2,28,248,22,181,13,23,194,2,91,159,39,11,90, -161,39,36,11,248,22,138,14,23,197,1,87,95,83,160,38,11,80,158,45,47, +22,73,23,199,2,249,22,136,14,23,195,1,28,248,22,79,23,197,1,87,94, +23,197,1,6,8,8,109,97,105,110,46,114,107,116,249,22,137,7,23,199,1, +6,4,4,46,114,107,116,28,248,22,178,6,23,198,2,87,94,23,194,1,27, +27,28,23,200,2,28,249,22,185,8,23,202,2,80,158,43,47,80,158,41,48, +27,248,22,188,4,23,202,2,28,248,22,182,13,23,194,2,91,159,39,11,90, +161,39,36,11,248,22,139,14,23,197,1,87,95,83,160,38,11,80,158,45,47, 23,204,2,83,160,38,11,80,158,45,48,192,192,11,11,28,23,193,2,192,87, -94,23,193,1,27,247,22,145,5,28,23,193,2,192,87,94,23,193,1,247,22, -158,14,27,250,22,150,2,80,159,44,44,38,249,22,71,23,204,2,23,199,2, +94,23,193,1,27,247,22,146,5,28,23,193,2,192,87,94,23,193,1,247,22, +159,14,27,250,22,150,2,80,159,44,44,38,249,22,71,23,204,2,23,199,2, 11,28,23,193,2,192,87,94,23,193,1,91,159,38,11,90,161,38,36,11,248, -2,55,248,2,57,23,203,2,250,22,1,22,135,14,23,199,1,249,22,85,249, +2,55,248,2,57,23,203,2,250,22,1,22,136,14,23,199,1,249,22,85,249, 22,2,32,0,89,162,8,44,37,44,9,222,33,59,23,200,1,248,22,81,27, -248,22,180,6,23,202,2,28,249,22,180,3,194,39,28,249,22,183,6,2,28, -249,22,135,7,204,249,22,168,3,198,39,249,22,136,7,250,22,135,7,205,36, -249,22,168,3,199,39,2,29,200,200,28,248,22,181,13,23,198,2,87,94,23, -194,1,28,248,22,140,14,23,198,2,27,248,22,144,14,23,199,2,91,159,39, -11,90,161,39,36,11,248,22,138,14,23,197,2,87,95,23,195,1,23,193,1, -28,249,22,168,14,2,60,248,22,186,13,23,197,1,249,80,159,45,53,38,23, +248,22,181,6,23,202,2,28,249,22,180,3,194,39,28,249,22,184,6,2,28, +249,22,136,7,204,249,22,168,3,198,39,249,22,137,7,250,22,136,7,205,36, +249,22,168,3,199,39,2,29,200,200,28,248,22,182,13,23,198,2,87,94,23, +194,1,28,248,22,141,14,23,198,2,27,248,22,145,14,23,199,2,91,159,39, +11,90,161,39,36,11,248,22,139,14,23,197,2,87,95,23,195,1,23,193,1, +28,249,22,169,14,2,60,248,22,187,13,23,197,1,249,80,159,45,53,38,23, 198,1,2,30,195,248,22,81,6,26,26,32,40,97,32,112,97,116,104,32,109, -117,115,116,32,98,101,32,97,98,115,111,108,117,116,101,41,28,249,22,184,8, +117,115,116,32,98,101,32,97,98,115,111,108,117,116,101,41,28,249,22,185,8, 248,22,72,23,200,2,2,27,27,250,22,150,2,80,159,43,44,38,249,22,71, -23,203,2,247,22,159,14,11,28,23,193,2,192,87,94,23,193,1,91,159,39, +23,203,2,247,22,160,14,11,28,23,193,2,192,87,94,23,193,1,91,159,39, 11,90,161,38,36,11,27,248,22,96,23,203,2,248,2,61,248,2,63,23,195, 1,90,161,37,38,11,28,248,22,79,248,22,98,23,203,2,28,248,22,79,23, -194,2,249,22,172,14,0,8,35,114,120,34,91,46,93,34,23,196,2,11,10, +194,2,249,22,173,14,0,8,35,114,120,34,91,46,93,34,23,196,2,11,10, 27,27,28,23,197,2,249,22,85,28,248,22,79,248,22,98,23,207,2,21,93, 6,5,5,109,122,108,105,98,249,22,1,22,85,249,22,2,32,0,89,162,8, 44,37,44,9,222,33,67,248,22,98,23,210,2,23,197,2,28,248,22,79,23, 196,2,248,22,81,23,197,2,23,195,2,251,80,159,49,54,38,2,18,23,204, -1,248,22,72,23,198,2,248,22,73,23,198,1,249,22,135,14,23,195,1,28, -23,198,1,87,94,23,196,1,27,248,22,180,6,23,199,2,28,249,22,180,3, -194,39,28,249,22,183,6,2,28,249,22,135,7,201,249,22,168,3,198,39,249, -22,136,7,250,22,135,7,202,36,249,22,168,3,199,39,2,29,197,197,28,248, +1,248,22,72,23,198,2,248,22,73,23,198,1,249,22,136,14,23,195,1,28, +23,198,1,87,94,23,196,1,27,248,22,181,6,23,199,2,28,249,22,180,3, +194,39,28,249,22,184,6,2,28,249,22,136,7,201,249,22,168,3,198,39,249, +22,137,7,250,22,136,7,202,36,249,22,168,3,199,39,2,29,197,197,28,248, 22,79,23,197,1,87,94,23,197,1,6,8,8,109,97,105,110,46,114,107,116, -28,249,22,172,14,0,8,35,114,120,34,91,46,93,34,23,199,2,27,248,22, -180,6,23,199,2,28,249,22,180,3,194,39,28,249,22,183,6,2,28,249,22, -135,7,201,249,22,168,3,198,39,249,22,136,7,250,22,135,7,202,36,249,22, -168,3,199,39,2,29,197,197,249,22,136,7,23,199,1,6,4,4,46,114,107, -116,28,249,22,184,8,248,22,72,23,200,2,64,102,105,108,101,27,248,22,144, -14,249,22,142,14,248,22,146,14,248,22,96,23,203,2,27,28,23,203,2,28, -249,22,184,8,23,205,2,80,158,46,47,80,158,44,48,27,248,22,188,4,23, -205,2,28,248,22,181,13,23,194,2,91,159,39,11,90,161,39,36,11,248,22, -138,14,23,197,1,87,95,83,160,38,11,80,158,48,47,23,207,2,83,160,38, +28,249,22,173,14,0,8,35,114,120,34,91,46,93,34,23,199,2,27,248,22, +181,6,23,199,2,28,249,22,180,3,194,39,28,249,22,184,6,2,28,249,22, +136,7,201,249,22,168,3,198,39,249,22,137,7,250,22,136,7,202,36,249,22, +168,3,199,39,2,29,197,197,249,22,137,7,23,199,1,6,4,4,46,114,107, +116,28,249,22,185,8,248,22,72,23,200,2,64,102,105,108,101,27,248,22,145, +14,249,22,143,14,248,22,147,14,248,22,96,23,203,2,27,28,23,203,2,28, +249,22,185,8,23,205,2,80,158,46,47,80,158,44,48,27,248,22,188,4,23, +205,2,28,248,22,182,13,23,194,2,91,159,39,11,90,161,39,36,11,248,22, +139,14,23,197,1,87,95,83,160,38,11,80,158,48,47,23,207,2,83,160,38, 11,80,158,48,48,192,192,11,11,28,23,193,2,192,87,94,23,193,1,27,247, -22,145,5,28,23,193,2,192,87,94,23,193,1,247,22,158,14,91,159,39,11, -90,161,39,36,11,248,22,138,14,23,197,2,87,95,23,195,1,23,193,1,28, -249,22,168,14,2,60,248,22,186,13,23,197,1,249,80,159,45,53,38,23,198, -1,2,30,195,12,87,94,28,28,248,22,181,13,23,194,2,10,248,22,136,8, -23,194,2,87,94,23,199,1,12,28,23,199,2,250,22,153,9,67,114,101,113, -117,105,114,101,249,22,161,7,6,17,17,98,97,100,32,109,111,100,117,108,101, +22,146,5,28,23,193,2,192,87,94,23,193,1,247,22,159,14,91,159,39,11, +90,161,39,36,11,248,22,139,14,23,197,2,87,95,23,195,1,23,193,1,28, +249,22,169,14,2,60,248,22,187,13,23,197,1,249,80,159,45,53,38,23,198, +1,2,30,195,12,87,94,28,28,248,22,182,13,23,194,2,10,248,22,137,8, +23,194,2,87,94,23,199,1,12,28,23,199,2,250,22,154,9,67,114,101,113, +117,105,114,101,249,22,162,7,6,17,17,98,97,100,32,109,111,100,117,108,101, 32,112,97,116,104,126,97,28,23,198,2,248,22,72,23,199,2,6,0,0,23, -202,1,87,94,23,199,1,250,22,154,9,2,18,249,22,161,7,6,13,13,109, +202,1,87,94,23,199,1,250,22,155,9,2,18,249,22,162,7,6,13,13,109, 111,100,117,108,101,32,112,97,116,104,126,97,28,23,198,2,248,22,72,23,199, -2,6,0,0,23,200,2,27,28,248,22,136,8,23,195,2,249,22,141,8,23, -196,2,36,249,22,144,14,248,22,145,14,23,197,2,11,27,28,248,22,136,8, -23,196,2,249,22,141,8,23,197,2,37,248,80,159,42,55,38,23,195,2,91, -159,39,11,90,161,39,36,11,28,248,22,136,8,23,199,2,250,22,7,2,31, -249,22,141,8,23,203,2,38,2,31,248,22,138,14,23,198,2,87,95,23,195, -1,23,193,1,27,28,248,22,136,8,23,200,2,249,22,141,8,23,201,2,39, -249,80,159,47,53,38,23,197,2,5,0,27,28,248,22,136,8,23,201,2,249, -22,141,8,23,202,2,40,248,22,187,4,23,200,2,27,27,250,22,150,2,80, -159,51,43,38,248,22,129,15,247,22,161,12,11,28,23,193,2,192,87,94,23, -193,1,27,247,22,130,2,87,94,250,22,148,2,80,159,52,43,38,248,22,129, -15,247,22,161,12,195,192,87,95,28,23,208,1,27,250,22,150,2,23,197,2, +2,6,0,0,23,200,2,27,28,248,22,137,8,23,195,2,249,22,142,8,23, +196,2,36,249,22,145,14,248,22,146,14,23,197,2,11,27,28,248,22,137,8, +23,196,2,249,22,142,8,23,197,2,37,248,80,159,42,55,38,23,195,2,91, +159,39,11,90,161,39,36,11,28,248,22,137,8,23,199,2,250,22,7,2,31, +249,22,142,8,23,203,2,38,2,31,248,22,139,14,23,198,2,87,95,23,195, +1,23,193,1,27,28,248,22,137,8,23,200,2,249,22,142,8,23,201,2,39, +249,80,159,47,53,38,23,197,2,5,0,27,28,248,22,137,8,23,201,2,249, +22,142,8,23,202,2,40,248,22,187,4,23,200,2,27,27,250,22,150,2,80, +159,51,43,38,248,22,130,15,247,22,162,12,11,28,23,193,2,192,87,94,23, +193,1,27,247,22,130,2,87,94,250,22,148,2,80,159,52,43,38,248,22,130, +15,247,22,162,12,195,192,87,95,28,23,208,1,27,250,22,150,2,23,197,2, 197,11,28,23,193,1,12,87,95,27,27,28,248,22,17,80,159,51,46,38,80, 159,50,46,38,247,22,19,250,22,25,248,22,23,23,197,2,80,159,53,45,38, -23,196,1,27,248,22,129,15,247,22,161,12,249,22,3,83,158,40,20,100,94, +23,196,1,27,248,22,130,15,247,22,162,12,249,22,3,83,158,40,20,100,94, 89,162,8,44,37,55,9,226,12,11,2,3,33,68,23,195,1,23,196,1,248, 28,248,22,17,80,159,50,46,38,32,0,89,162,44,37,42,9,222,33,69,80, 159,49,59,37,89,162,44,36,51,9,227,13,9,8,4,3,33,70,250,22,148, -2,23,197,1,197,10,12,28,28,248,22,136,8,23,202,1,11,28,248,22,177, +2,23,197,1,197,10,12,28,28,248,22,137,8,23,202,1,11,28,248,22,178, 6,23,206,2,10,28,248,22,56,23,206,2,10,28,248,22,69,23,206,2,249, -22,184,8,248,22,72,23,208,2,2,27,11,250,22,148,2,80,159,50,44,38, -28,248,22,177,6,23,209,2,249,22,71,23,210,1,27,28,23,212,2,28,249, -22,184,8,23,214,2,80,158,55,47,87,94,23,212,1,80,158,53,48,27,248, -22,188,4,23,214,2,28,248,22,181,13,23,194,2,91,159,39,11,90,161,39, -36,11,248,22,138,14,23,197,1,87,95,83,160,38,11,80,158,57,47,23,23, +22,185,8,248,22,72,23,208,2,2,27,11,250,22,148,2,80,159,50,44,38, +28,248,22,178,6,23,209,2,249,22,71,23,210,1,27,28,23,212,2,28,249, +22,185,8,23,214,2,80,158,55,47,87,94,23,212,1,80,158,53,48,27,248, +22,188,4,23,214,2,28,248,22,182,13,23,194,2,91,159,39,11,90,161,39, +36,11,248,22,139,14,23,197,1,87,95,83,160,38,11,80,158,57,47,23,23, 83,160,38,11,80,158,57,48,192,192,11,11,28,23,193,2,192,87,94,23,193, -1,27,247,22,145,5,28,23,193,2,192,87,94,23,193,1,247,22,158,14,249, -22,71,23,210,1,247,22,159,14,252,22,138,8,23,208,1,23,207,1,23,205, +1,27,247,22,146,5,28,23,193,2,192,87,94,23,193,1,247,22,159,14,249, +22,71,23,210,1,247,22,160,14,252,22,139,8,23,208,1,23,207,1,23,205, 1,23,203,1,201,12,193,87,96,83,160,38,11,80,158,36,50,248,80,159,37, 58,38,249,22,27,11,80,159,39,52,38,248,22,166,4,80,159,37,51,38,248, -22,144,5,80,159,37,37,37,248,22,152,13,80,159,37,42,37,83,160,38,11, +22,145,5,80,159,37,37,37,248,22,153,13,80,159,37,42,37,83,160,38,11, 80,158,36,50,248,80,159,37,58,38,249,22,27,11,80,159,39,52,38,159,36, 20,105,159,36,16,1,11,16,0,83,158,42,20,103,145,2,1,2,1,29,11, 11,11,11,11,10,38,80,158,36,36,20,105,159,37,16,23,2,2,2,3,30, @@ -734,7 +734,7 @@ 16,2,2,20,2,21,38,38,37,11,11,11,16,0,16,0,16,0,36,36,11, 11,11,11,16,0,16,0,16,0,36,36,16,0,16,15,83,158,36,16,2,89, 162,44,37,45,9,223,0,33,32,80,159,36,59,37,83,158,36,16,2,248,22, -133,8,69,115,111,45,115,117,102,102,105,120,80,159,36,36,37,83,158,36,16, +134,8,69,115,111,45,115,117,102,102,105,120,80,159,36,36,37,83,158,36,16, 2,89,162,44,38,8,37,2,3,223,0,33,41,80,159,36,37,37,83,158,36, 16,2,32,0,89,162,8,44,37,42,2,9,222,192,80,159,36,42,37,83,158, 36,16,2,247,22,133,2,80,159,36,43,37,83,158,36,16,2,247,22,132,2, diff --git a/src/racket/src/env.c b/src/racket/src/env.c index 8b19992879..43eb445b52 100644 --- a/src/racket/src/env.c +++ b/src/racket/src/env.c @@ -357,9 +357,11 @@ Scheme_Env *scheme_engine_instance_init() { #endif make_kernel_env(); -#if defined(MZ_PRECISE_GC) && defined(MZ_USE_PLACES) - scheme_places_block_child_signal(); +#if defined(MZ_PLACES_WAITPID) + scheme_places_start_child_signal_handler(); +#endif +#if defined(MZ_PRECISE_GC) && defined(MZ_USE_PLACES) GC_switch_out_master_gc(); scheme_spawn_master_place(); diff --git a/src/racket/src/mzrt.c b/src/racket/src/mzrt.c index 507689fc1f..e08086a370 100644 --- a/src/racket/src/mzrt.c +++ b/src/racket/src/mzrt.c @@ -160,12 +160,22 @@ void *mzrt_thread_stub(void *data){ mzrt_thread_stub_data *stub_data = (mzrt_thread_stub_data*) data; mz_proc_thread_start start_proc = stub_data->start_proc; void *start_proc_data = stub_data->data; + void* res; + scheme_init_os_thread(); - proc_thread_self = stub_data->thread; + + proc_thread_self = stub_data->thread; free(data); - return start_proc(start_proc_data); + res = start_proc(start_proc_data); + + if (proc_thread_self->refcount) + free(proc_thread_self); + + scheme_done_os_thread(); + + return res; } #ifdef WIN32 @@ -196,11 +206,14 @@ mz_proc_thread* mzrt_proc_first_thread_init() { thread->mbox = pt_mbox_create(); thread->threadid = mz_proc_thread_self(); proc_thread_self = thread; + thread->refcount = 1; return thread; } mz_proc_thread* mz_proc_thread_create_w_stacksize(mz_proc_thread_start start_proc, void* data, long stacksize) { mz_proc_thread *thread = (mz_proc_thread*)malloc(sizeof(mz_proc_thread)); + mzrt_thread_stub_data *stub_data; + # ifndef WIN32 pthread_attr_t *attr; pthread_attr_t attr_storage; @@ -213,7 +226,10 @@ mz_proc_thread* mz_proc_thread_create_w_stacksize(mz_proc_thread_start start_pro attr = NULL; # endif - mzrt_thread_stub_data *stub_data = (mzrt_thread_stub_data*)malloc(sizeof(mzrt_thread_stub_data)); + thread->refcount = 2; + + stub_data = (mzrt_thread_stub_data*)malloc(sizeof(mzrt_thread_stub_data)); + thread->mbox = pt_mbox_create(); stub_data->start_proc = start_proc; stub_data->data = data; @@ -221,7 +237,11 @@ mz_proc_thread* mz_proc_thread_create_w_stacksize(mz_proc_thread_start start_pro # ifdef WIN32 thread->threadid = CreateThread(NULL, stacksize, mzrt_win_thread_stub, stub_data, 0, NULL); # else +# ifdef MZ_PRECISE_GC pthread_create(&thread->threadid, attr, mzrt_thread_stub, stub_data); +# else + GC_pthread_create(&thread->threadid, attr, mzrt_thread_stub, stub_data); +# endif # endif return thread; @@ -240,34 +260,43 @@ mz_proc_thread* mz_proc_thread_create(mz_proc_thread_start start_proc, void* dat } void * mz_proc_thread_wait(mz_proc_thread *thread) { -#ifdef WIN32 - DWORD rc; - WaitForSingleObject(thread->threadid,INFINITE); - GetExitCodeThread(thread->threadid, &rc); - return (void *) rc; -#else void *rc; +#ifdef WIN32 + DWORD rcw; + WaitForSingleObject(thread->threadid,INFINITE); + GetExitCodeThread(thread->threadid, &rcw); + rc = (void *)rcw; + CloseHandle(thread->threadid); +#else # ifndef MZ_PRECISE_GC GC_pthread_join(thread->threadid, &rc); # else pthread_join(thread->threadid, &rc); # endif - return rc; #endif + + if (!--thread->refcount) + free(thread); + + return rc; } int mz_proc_thread_detach(mz_proc_thread *thread) { -#ifdef WIN32 - return CloseHandle(thread->threadid); -#else int rc; +#ifdef WIN32 + rc = CloseHandle(thread->threadid); +#else # ifndef MZ_PRECISE_GC rc = GC_pthread_detach(thread->threadid); # else rc = pthread_detach(thread->threadid); # endif - return rc; #endif + + if (!--thread->refcount) + free(thread); + + return rc; } void mz_proc_thread_exit(void *rc) { diff --git a/src/racket/src/mzrt.h b/src/racket/src/mzrt.h index 4a0d1d8ca3..191affd668 100644 --- a/src/racket/src/mzrt.h +++ b/src/racket/src/mzrt.h @@ -34,6 +34,7 @@ typedef pthread_t mzrt_thread_id; typedef struct mz_proc_thread { mzrt_thread_id threadid; + int refcount; struct pt_mbox *mbox; } mz_proc_thread; diff --git a/src/racket/src/places.c b/src/racket/src/places.c index 2f19367444..1b4b718a33 100644 --- a/src/racket/src/places.c +++ b/src/racket/src/places.c @@ -6,6 +6,9 @@ #ifdef MZ_USE_PLACES #include "mzrt.h" +#ifdef UNIX_PROCESSES +# include +#endif READ_ONLY static Scheme_Object *scheme_def_place_exit_proc; @@ -202,147 +205,393 @@ Scheme_Object *scheme_place(int argc, Scheme_Object *args[]) { return (Scheme_Object*) place; } -# ifdef MZ_PRECISE_GC -/*============= SIGNAL HANDLER =============*/ +# if defined(MZ_PLACES_WAITPID) +/*============= SIGCHLD SIGNAL HANDLING =============*/ + +/* If SIGCHLD is unblocked, it gets delivered to a random thread + --- not necessarily on in the right place for the subprocess. + To avoid that problem, we centralize SIGCHLD handling here, and + then dispatch back out to specific places as they request + information. */ + #include #include #include #include - -static void error_info() { - char *erstr; - erstr = strerror(errno); - printf("errno %i %s\n", errno, erstr); -} - typedef struct Child_Status { int pid; int status; + char done; + char unneeded; /* not in a group; result not needed */ + char is_group; void *signal_fd; struct Child_Status *next; + struct Child_Status *next_group; /* see child_group_statuses */ } Child_Status; SHARED_OK static Child_Status *child_statuses = NULL; SHARED_OK static mzrt_mutex* child_status_lock = NULL; +SHARED_OK static mzrt_mutex* child_wait_lock = NULL; /* ordered before status lock */ + +/* When a process for a process group becomes unreachable + before a waitpid() on the process, then we need to keep + waiting on it to let the OS gc the process. Otherwise, + we wait only on processes in the same group as Racket. + This list is protect by the wait lock. */ +SHARED_OK static Child_Status *child_group_statuses = NULL; + +static void add_group_signal_fd(void *signal_fd); +static void remove_group_signal_fd(void *signal_fd); +static void do_group_signal_fds(); static void add_child_status(int pid, int status) { Child_Status *st; - st = malloc(sizeof(Child_Status)); - st->pid = pid; - st->signal_fd = NULL; - st->status = status; + /* Search for existing record, which will have a signal_fd: */ mzrt_mutex_lock(child_status_lock); - st->next = child_statuses; - child_statuses = st; + for (st = child_statuses; st; st = st->next) { + if (st->pid == pid) + break; + } + + if (!st) { + /* must have terminated before it was registered + (and since we detected it, it must not be a group) */ + st = malloc(sizeof(Child_Status)); + st->pid = pid; + st->signal_fd = NULL; + st->next = child_statuses; + child_statuses = st; + st->next_group = NULL; + st->unneeded = 0; + st->is_group = 0; + } + st->status = status; + st->done = 1; + + if (st->signal_fd && st->is_group) + remove_group_signal_fd(st->signal_fd); + mzrt_mutex_unlock(child_status_lock); + + if (st->signal_fd) + scheme_signal_received_at(st->signal_fd); + if (st->unneeded) + (void)scheme_get_child_status(st->pid, 0, NULL); } -static int raw_get_child_status(int pid, int *status) { +static int raw_get_child_status(int pid, int *status, int done_only, int do_remove, int do_free) { Child_Status *st; Child_Status *prev; int found = 0; for (st = child_statuses, prev = NULL; st; prev = st, st = st->next) { if (st->pid == pid) { - *status = st->status; - found = 1; - if (prev) { - prev->next = st->next; + if (!done_only || st->done) { + if (status) + *status = st->status; + found = 1; + if (do_remove) { + if (prev) + prev->next = st->next; + else + child_statuses = st->next; + } + if (do_free) + free(st); } - else { - child_statuses = st->next; - } - free(st); break; } } return found; } -int scheme_get_child_status(int pid, int *status) { +int scheme_get_child_status(int pid, int is_group, int *status) { int found = 0; + + if (is_group) { + /* need to specifically try the pid, since we don't + wait on other process groups in the background thread */ + pid_t pid2; + int status; + + do { + pid2 = waitpid((pid_t)pid, &status, WNOHANG); + } while ((pid2 == -1) && (errno == EINTR)); + + if (pid2 > 0) + add_child_status(pid, status); + } + mzrt_mutex_lock(child_status_lock); - found = raw_get_child_status(pid, status); + found = raw_get_child_status(pid, status, 1, 1, 1); mzrt_mutex_unlock(child_status_lock); /* printf("scheme_get_child_status found %i pid %i status %i\n", found, pid, *status); */ + return found; } -int scheme_places_register_child(int pid, void *signal_fd, int *status) { +int scheme_places_register_child(int pid, int is_group, void *signal_fd, int *status) +{ int found = 0; mzrt_mutex_lock(child_status_lock); - found = raw_get_child_status(pid, status); + + /* The child may have terminated already: */ + found = raw_get_child_status(pid, status, 0, 0, 0); + if (!found) { + /* Create a record for the child: */ Child_Status *st; st = malloc(sizeof(Child_Status)); st->pid = pid; st->signal_fd = signal_fd; st->status = 0; + st->unneeded = 0; + st->done = 0; + st->is_group = is_group; st->next = child_statuses; child_statuses = st; + st->next_group = NULL; + + if (is_group) + add_group_signal_fd(signal_fd); } + mzrt_mutex_unlock(child_status_lock); return found; } static void *mz_proc_thread_signal_worker(void *data) { int status; - int pid; + int pid, check_pid, is_group; sigset_t set; - //GC_CAN_IGNORE siginfo_t info; - { - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - pthread_sigmask(SIG_UNBLOCK, &set, NULL); - } + Child_Status *group_status, *prev_group; - while(1) { + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + + while (1) { int rc; int signalid; + do { rc = sigwait(&set, &signalid); if (rc == -1) { - if (errno != EINTR ) { - error_info(); + if (errno != EINTR) { + fprintf(stderr, "unexpected error from sigwait(): %d\n", errno); } } } while (rc == -1 && errno == EINTR); - pid = waitpid((pid_t)-1, &status, WNOHANG); - if (pid == -1) { - char *erstr; - erstr = strerror(errno); - /* printf("errno %i %s\n", errno, erstr); */ - } - else { - /* printf("SIGCHILD pid %i with status %i %i\n", pid, status, WEXITSTATUS(status)); */ - add_child_status(pid, status); - } - }; + mzrt_mutex_lock(child_status_lock); + do_group_signal_fds(); + mzrt_mutex_unlock(child_status_lock); + + mzrt_mutex_lock(child_wait_lock); + + group_status = child_group_statuses; + prev_group = NULL; + + do { + if (group_status) { + check_pid = group_status->pid; + is_group = 1; + } else { + check_pid = 0; /* => processes in the same group as Racket */ + is_group = 0; + } + + pid = waitpid(check_pid, &status, WNOHANG); + + if (pid == -1) { + if (errno == EINTR) { + /* try again */ + pid = 1; + } else if (!is_group && (errno == ECHILD)) { + /* no more to check */ + } else { + fprintf(stderr, "unexpected error from waitpid(%d[%d]): %d\n", + check_pid, is_group, errno); + if (is_group) { + prev_group = group_status; + group_status = group_status->next; + } + } + } else if (pid > 0) { + /* printf("SIGCHILD pid %i with status %i %i\n", pid, status, WEXITSTATUS(status)); */ + if (is_group) { + group_status = group_status->next; + if (prev_group) + prev_group->next_group = group_status; + else + child_group_statuses = group_status; + } else + add_child_status(pid, status); + } else { + if (is_group) { + prev_group = group_status; + group_status = group_status->next; + } + } + } while ((pid > 0) || is_group); + + mzrt_mutex_unlock(child_wait_lock); + } + return NULL; } +void scheme_done_with_process_id(int pid, int is_group) +{ + Child_Status *st; -void scheme_places_block_child_signal() { - { - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - pthread_sigmask(SIG_BLOCK, &set, NULL); + mzrt_mutex_lock(child_wait_lock); /* protects child_group_statuses */ + mzrt_mutex_lock(child_status_lock); + + for (st = child_statuses; st; st = st->next) { + if (st->pid == pid) { + if (!st->done) { + if (is_group) { + st->next_group = child_group_statuses; + child_group_statuses = st; + if (st->signal_fd) + remove_group_signal_fd(st->signal_fd); + } else + st->unneeded = 1; + st->signal_fd = NULL; + } + break; + } + } + + if (st && (is_group || st->done)) { + /* remove it from normal list: */ + raw_get_child_status(pid, NULL, 0, 1, !st->done); } - { - mz_proc_thread *signal_thread; - mzrt_mutex_create(&child_status_lock); - signal_thread = mz_proc_thread_create(mz_proc_thread_signal_worker, NULL); - mz_proc_thread_detach(signal_thread); + mzrt_mutex_unlock(child_status_lock); + mzrt_mutex_unlock(child_wait_lock); +} + +static void got_sigchld() XFORM_SKIP_PROC +{ + write(2, "SIGCHLD handler called (some thread has SIGCHLD unblocked)\n", 59); +} + +void scheme_places_block_child_signal() XFORM_SKIP_PROC +{ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, NULL); + + /* Mac OS X seems to need a handler installed for SIGCHLD to be + delivered, since the default is to drop the signal. Also, this + handler serves as a back-up alert if some thread is created that + does not block SIGCHLD. */ + MZ_SIGSET(SIGCHLD, got_sigchld); +} + +void scheme_places_start_child_signal_handler() +{ + mz_proc_thread *signal_thread; + + mzrt_mutex_create(&child_status_lock); + mzrt_mutex_create(&child_wait_lock); + + signal_thread = mz_proc_thread_create(mz_proc_thread_signal_worker, NULL); + mz_proc_thread_detach(signal_thread); +} + +void scheme_wait_suspend() +{ + mzrt_mutex_lock(child_wait_lock); +} + +void scheme_wait_resume() +{ + mzrt_mutex_unlock(child_wait_lock); +} + +/* ---------------------------------------------------------------------- */ + +/* When a place has a process-group that it may be waiting on, the we + need to wake up the place whenever any SIGCHLD is received, since + the SIGDCHLD may apply to one of those places. + The list of signal_fds is protected by the status lock. */ + +typedef struct Group_Signal_FD { + void *signal_fd; + int refcount; +} Group_Signal_FD; + +SHARED_OK static Group_Signal_FD *signal_fds; +SHARED_OK static int signal_fd_count; + +static void add_group_signal_fd(void *signal_fd) +{ + int i, count = 0; + Group_Signal_FD *a; + + for (i = 0; i < signal_fd_count; i++) { + if (signal_fds[i].refcount) { + count++; + if (signal_fds[i].signal_fd == signal_fd) { + signal_fds[i].refcount++; + return; + } + } + } + + if (count == signal_fd_count) { + signal_fd_count = (signal_fd_count + 4) * 2; + a = (Group_Signal_FD *)malloc(sizeof(Group_Signal_FD) * signal_fd_count); + memset(a, 0, sizeof(Group_Signal_FD) * signal_fd_count); + memcpy(a, signal_fds, sizeof(Group_Signal_FD) * count); + signal_fds = a; + } + + for (i = 0; i < signal_fd_count; i++) { + if (!signal_fds[i].refcount) { + signal_fds[i].signal_fd = signal_fd; + signal_fds[i].refcount = 1; + break; + } } } +static void remove_group_signal_fd(void *signal_fd) +{ + int i; + + for (i = 0; i < signal_fd_count; i++) { + if (signal_fds[i].refcount) { + if (signal_fds[i].signal_fd == signal_fd) { + --signal_fds[i].refcount; + return; + } + } + } +} + +static void do_group_signal_fds() +{ + int i; + + for (i = 0; i < signal_fd_count; i++) { + if (signal_fds[i].refcount) { + scheme_signal_received_at(signal_fds[i].signal_fd); + } + } +} + +#endif + +# if defined(MZ_PRECISE_GC) + /*============= THREAD JOIN HANDLER =============*/ typedef struct { mz_proc_thread *proc_thread; diff --git a/src/racket/src/port.c b/src/racket/src/port.c index 9d249aa3d3..20b54c93cd 100644 --- a/src/racket/src/port.c +++ b/src/racket/src/port.c @@ -169,7 +169,7 @@ int scheme_stupid_windows_machine; /******************** Unix Subprocesses ********************/ -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) /* For process & system: */ typedef struct System_Child { MZTAG_IF_REQUIRED @@ -186,7 +186,8 @@ typedef struct Scheme_Subprocess { Scheme_Object so; void *handle; int pid; -#if defined(UNIX_PROCESSES) && defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) + int is_group; +#if defined(MZ_PLACES_WAITPID) short done; int status; #endif @@ -374,6 +375,7 @@ static Scheme_Object *subprocess_p(int c, Scheme_Object *args[]); static Scheme_Object *subprocess_wait(int c, Scheme_Object *args[]); static Scheme_Object *sch_shell_execute(int c, Scheme_Object *args[]); static Scheme_Object *current_subproc_cust_mode (int, Scheme_Object *[]); +static Scheme_Object *subproc_group_on (int, Scheme_Object *[]); static void register_subprocess_wait(); typedef struct Scheme_Read_Write_Evt { @@ -494,7 +496,7 @@ scheme_init_port (Scheme_Env *env) REGISTER_SO(scheme_null_output_port_type); REGISTER_SO(scheme_redirect_output_port_type); -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) REGISTER_SO(scheme_system_children); #endif @@ -570,6 +572,7 @@ scheme_init_port (Scheme_Env *env) scheme_add_global_constant("subprocess?", scheme_make_prim_w_arity(subprocess_p, "subprocess?", 1, 1), env); scheme_add_global_constant("subprocess-wait", scheme_make_prim_w_arity(subprocess_wait, "subprocess-wait", 1, 1), env); + GLOBAL_PARAMETER("subprocess-group-enabled", subproc_group_on, MZCONFIG_SUBPROC_GROUP_ENABLED, env); GLOBAL_PARAMETER("current-subprocess-custodian-mode", current_subproc_cust_mode, MZCONFIG_SUBPROC_CUSTODIAN_MODE, env); register_subprocess_wait(); @@ -6784,27 +6787,27 @@ static int MyPipe(int *ph, int near_index) { /**************** Unix: signal stuff ******************/ -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) - -# define WAITANY(s) waitpid((pid_t)-1, s, WNOHANG) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) #ifndef MZ_PRECISE_GC # define GC_write_barrier(x) /* empty */ #endif +SHARED_OK static void *unused_groups; + static int need_to_check_children; void scheme_block_child_signals(int block) XFORM_SKIP_PROC { -#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if !defined(MZ_PLACES_WAITPID) sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs, SIGCHLD); -#ifdef USE_ITIMER +# ifdef USE_ITIMER sigaddset(&sigs, SIGPROF); -#endif +# endif sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL); #endif } @@ -6824,7 +6827,7 @@ static int sigchld_installed = 0; static void init_sigchld(void) { -#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if !defined(MZ_PLACES_WAITPID) if (!sigchld_installed) { /* Catch child-done signals */ START_XFORM_SKIP; @@ -6836,21 +6839,39 @@ static void init_sigchld(void) #endif } -static void check_child_done() +static void check_child_done(pid_t pid) { - pid_t result; - int status; + pid_t result, check_pid; + int status, is_group; System_Child *sc, *prev; + void **unused = (void **)unused_groups, **unused_prev = NULL; if (scheme_system_children) { do { + if (!pid && unused) { + check_pid = (pid_t)(long)unused[0]; + is_group = 1; + } else { + check_pid = pid; + is_group = 0; + } + do { START_XFORM_SKIP; - result = WAITANY(&status); + result = waitpid(check_pid, &status, WNOHANG); END_XFORM_SKIP; } while ((result == -1) && (errno == EINTR)); if (result > 0) { + if (is_group) { + /* done with an inaccessible group id */ + unused = (void **)unused[1]; + if (unused_prev) + unused_prev[1] = unused; + else + unused_groups = unused; + } + START_XFORM_SKIP; if (WIFEXITED(status)) status = WEXITSTATUS(status); @@ -6870,8 +6891,13 @@ static void check_child_done() scheme_system_children = sc->next; } } + } else { + if (is_group) { + unused_prev = unused; + unused = unused[1]; + } } - } while (result > 0); + } while ((result > 0) || is_group); } } @@ -6879,7 +6905,7 @@ void scheme_check_child_done(void) { if (need_to_check_children) { need_to_check_children = 0; - check_child_done(); + check_child_done(0); } } @@ -7088,11 +7114,11 @@ static int subp_done(Scheme_Object *so) sp = (Scheme_Subprocess*) so; #if defined(UNIX_PROCESSES) -# if defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) +# if defined(MZ_PLACES_WAITPID) { int status; if (!sp->done) { - if (scheme_get_child_status(((Scheme_Subprocess *)sp)->pid, &status)) { + if (scheme_get_child_status(sp->pid, sp->is_group, &status)) { sp->done = 1; sp->status = status; child_mref_done(sp); @@ -7106,8 +7132,8 @@ static int subp_done(Scheme_Object *so) # else { System_Child *sc; - sc = ((System_Child *) ((Scheme_Subprocess *)sp)->handle); - check_child_done(); + sc = (System_Child *)sp->handle; + check_child_done(sp->is_group ? sp->pid : 0); if (sc->done) child_mref_done(sp); return sc->done; @@ -7151,17 +7177,21 @@ static Scheme_Object *subprocess_status(int argc, Scheme_Object **argv) int going = 0, status = MZ_FAILURE_STATUS; #if defined(UNIX_PROCESSES) -# if defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) +# if defined(MZ_PLACES_WAITPID) if (sp->done) status = sp->status; else { - if(!scheme_get_child_status(((Scheme_Subprocess *)sp)->pid, &status)) { + if (!scheme_get_child_status(sp->pid, sp->is_group, &status)) { going = 1; + } else { + child_mref_done(sp); + sp->done = 1; + sp->status = status; } } # else System_Child *sc = (System_Child *)sp->handle; - check_child_done(); + check_child_done(sp->is_group ? sp->pid : 0); if (sc->done) { child_mref_done(sp); @@ -7230,13 +7260,22 @@ static Scheme_Object *do_subprocess_kill(Scheme_Object *_sp, Scheme_Object *kill Scheme_Subprocess *sp = (Scheme_Subprocess *)_sp; #if defined(UNIX_PROCESSES) -# if defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) +# if defined(MZ_PLACES_WAITPID) { int status; + if (sp->done) return scheme_void; - if (scheme_get_child_status(sp->pid, &status)) { + + scheme_wait_suspend(); + + /* Don't pass sp->is_group, because we don't want to wait + on a group if we haven't already: */ + if (scheme_get_child_status(sp->pid, 0, &status)) { + sp->status = status; + sp->done = 1; child_mref_done(sp); + scheme_wait_resume(); return scheme_void; } } @@ -7244,32 +7283,52 @@ static Scheme_Object *do_subprocess_kill(Scheme_Object *_sp, Scheme_Object *kill { System_Child *sc = (System_Child *)sp->handle; - check_child_done(); + /* Don't pass sp->pid, because we don't want to wait + on a group if we haven't already: */ + check_child_done(0); if (sc->done) { child_mref_done(sp); return scheme_void; } } +# define scheme_wait_resume() /* empty */ # endif while (1) { - if (!kill(sp->pid, SCHEME_TRUEP(killp) ? SIGKILL : SIGINT)) - return scheme_void; - + if (sp->is_group) { + if (!killpg(sp->pid, SCHEME_TRUEP(killp) ? SIGKILL : SIGINT)) { + scheme_wait_resume(); + return scheme_void; + } + } else { + if (!kill(sp->pid, SCHEME_TRUEP(killp) ? SIGKILL : SIGINT)) { + scheme_wait_resume(); + return scheme_void; + } + } + if (errno != EINTR) break; /* Otherwise we were interrupted. Try `kill' again. */ } + + scheme_wait_resume(); + #else - if (SCHEME_TRUEP(killp)) { + if (SCHEME_TRUEP(killp) || sp->is_group) { DWORD w; int errid; if (!sp->handle) return scheme_void; - if (GetExitCodeProcess((HANDLE)sp->handle, &w)) { + if (SCHEME_FALSEP(killp)) { + /* must be for a group; we don't care whether the + original process is still running */ + if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, sp->pid)) + return scheme_void; + } else if (GetExitCodeProcess((HANDLE)sp->handle, &w)) { if (w != STILL_ACTIVE) return scheme_void; if (TerminateProcess((HANDLE)sp->handle, 1)) @@ -7333,9 +7392,8 @@ static Scheme_Object *subproc_cust_mode_p(int argc, Scheme_Object **argv) if (SCHEME_FALSEP(argv[0])) return argv[0]; if (SCHEME_SYMBOLP(argv[0]) && !SCHEME_SYM_WEIRDP(argv[0])) { - if (!strcmp(SCHEME_SYM_VAL(argv[0]), "kill")) - return argv[0]; - if (!strcmp(SCHEME_SYM_VAL(argv[0]), "interrupt")) + if (!strcmp(SCHEME_SYM_VAL(argv[0]), "kill") + || !strcmp(SCHEME_SYM_VAL(argv[0]), "interrupt")) return argv[0]; } @@ -7349,6 +7407,31 @@ static Scheme_Object *current_subproc_cust_mode (int argc, Scheme_Object *argv[] -1, subproc_cust_mode_p, "'interrupt, 'kill, or #f", 0); } +static Scheme_Object *subproc_group_on (int argc, Scheme_Object *argv[]) +{ + return scheme_param_config("subprocess-group-enabled", scheme_make_integer(MZCONFIG_SUBPROC_GROUP_ENABLED), + argc, argv, + -1, NULL, NULL, 1); +} + +#ifdef UNIX_PROCESSES +static void unused_process_group(void *_sp, void *ignored) +{ + Scheme_Subprocess *sp = (Scheme_Subprocess *)_sp; + +# if defined(MZ_PLACES_WAITPID) + if (!sp->done) + scheme_done_with_process_id(sp->pid, sp->is_group); +# else + void **unused_group; + unused_group = malloc(sizeof(void *) * 2); + unused_group[0] = (void *)sp->pid; + unused_group[1] = unused_groups; + need_to_check_children = 1; +# endif +} +#endif + /*********** Windows: command-line construction *************/ #ifdef WINDOWS_PROCESSES @@ -7408,7 +7491,8 @@ static char *cmdline_protect(char *s) } static long mz_spawnv(char *command, const char * const *argv, - int exact_cmdline, int sin, int sout, int serr, int *pid) + int exact_cmdline, int sin, int sout, int serr, int *pid, + int new_process_group) { int i, l, len = 0; long cr_flag; @@ -7451,6 +7535,8 @@ static long mz_spawnv(char *command, const char * const *argv, cr_flag = CREATE_NO_WINDOW; else cr_flag = 0; + if (new_process_group) + cr_flag |= CREATE_NEW_PROCESS_GROUP; if (CreateProcessW(WIDE_PATH_COPY(command), WIDE_PATH_COPY(cmdline), NULL, NULL, 1 /*inherit*/, @@ -7466,15 +7552,6 @@ static long mz_spawnv(char *command, const char * const *argv, static void close_subprocess_handle(void *sp, void *ignored) { Scheme_Subprocess *subproc = (Scheme_Subprocess *)sp; - #if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) - { - int status; - int pid = ((Scheme_Subprocess *)sp)->pid; - scheme_get_child_status(pid, &status) - /* printf("close_subprocess_handle pid %i status %i\n", pid status); */ - - } - #endif CloseHandle(subproc->handle); } @@ -7494,7 +7571,7 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) char **argv; Scheme_Object *in, *out, *err; #if defined(UNIX_PROCESSES) -# if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +# if !defined(MZ_PLACES_WAITPID) System_Child *sc; # endif int fork_errno = 0; @@ -7507,6 +7584,7 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) Scheme_Object *a[4]; Scheme_Subprocess *subproc; Scheme_Object *cust_mode; + int new_process_group; #if defined(WINDOWS_PROCESSES) int exact_cmdline = 0; #endif @@ -7647,6 +7725,8 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) if (!inport || !outport || !errport) scheme_custodian_check_available(NULL, name, "file-stream"); + cust_mode = scheme_get_param(scheme_current_config(), MZCONFIG_SUBPROC_GROUP_ENABLED); + new_process_group = SCHEME_TRUEP(cust_mode); cust_mode = scheme_get_param(scheme_current_config(), MZCONFIG_SUBPROC_CUSTODIAN_MODE); /*--------------------------------------*/ @@ -7706,7 +7786,8 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) to_subprocess[0], from_subprocess[1], err_subprocess[1], - &pid); + &pid, + new_process_group); if (spawn_status != -1) sc = (void *)spawn_status; @@ -7721,7 +7802,7 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) /*--------------------------------------*/ { -#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if !defined(MZ_PLACES_WAITPID) init_sigchld(); sc = MALLOC_ONE_RT(System_Child); @@ -7737,12 +7818,21 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) pid = fork(); if (pid > 0) { -#if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) + if (new_process_group) + /* there's a race condition between this use and the exec(), + and there's a race condition between the other setpgid() in + the child processand sending signals from the parent + process; so, we set in both, and at least one will + succeed; we could perform better error checking, since + EACCES is the only expected error */ + setpgid(pid, pid); + +#if defined(MZ_PLACES_WAITPID) { int *signal_fd; int status; signal_fd = scheme_get_signal_handle(); - scheme_places_register_child(pid, signal_fd, &status); + scheme_places_register_child(pid, new_process_group, signal_fd, &status); /* printf("SUBPROCESS %i\n", pid); */ } @@ -7780,11 +7870,14 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) } END_XFORM_SKIP; #endif + if (new_process_group) + /* see also setpgid above */ + setpgid(getpid(), getpid()); /* setpgid(0, 0) would work on some platforms */ } else { fork_errno = errno; } -#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if !defined(MZ_PLACES_WAITPID) scheme_block_child_signals(0); #endif } @@ -7934,26 +8027,28 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) subproc = MALLOC_ONE_TAGGED(Scheme_Subprocess); subproc->so.type = scheme_subprocess_type; -#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if !defined(MZ_PLACES_WAITPID) subproc->handle = (void *)sc; #endif subproc->pid = pid; + subproc->is_group = new_process_group; # if defined(WINDOWS_PROCESSES) scheme_add_finalizer(subproc, close_subprocess_handle, NULL); +# else + if (new_process_group) + scheme_add_finalizer(subproc, unused_process_group, NULL); # endif if (SCHEME_TRUEP(cust_mode)) { Scheme_Custodian_Reference *mref; + Scheme_Close_Custodian_Client *closer; + if (!strcmp(SCHEME_SYM_VAL(cust_mode), "kill")) - mref = scheme_add_managed(NULL, - (Scheme_Object *)subproc, - (Scheme_Close_Custodian_Client *)kill_subproc, - NULL, 1); + closer = kill_subproc; else - mref = scheme_add_managed(NULL, - (Scheme_Object *)subproc, - (Scheme_Close_Custodian_Client *)interrupt_subproc, - NULL, 1); + closer = interrupt_subproc; + + mref = scheme_add_managed(NULL, (Scheme_Object *)subproc, closer, NULL, 1); subproc->mref = mref; } @@ -8532,6 +8627,8 @@ static long WINAPI ITimer(void *data) WaitForSingleObject(itimer_semaphore, INFINITE); } } + + /* scheme_done_os_thread(); */ } static void scheme_start_itimer_thread(long usec) @@ -8582,6 +8679,7 @@ static void *green_thread_timer(void *data) while (1) { if (itimer_data->die) { + scheme_done_os_thread(); return NULL; } usleep(itimer_data->delay); @@ -8599,6 +8697,7 @@ static void *green_thread_timer(void *data) } pthread_mutex_unlock(&itimer_data->mutex); } + return NULL; } @@ -8934,7 +9033,7 @@ static void register_traversers(void) GC_REG_TRAV(scheme_rt_input_fd, mark_input_fd); #endif -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC)) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) GC_REG_TRAV(scheme_rt_system_child, mark_system_child); #endif diff --git a/src/racket/src/salloc.c b/src/racket/src/salloc.c index 6d95e44d6d..320753d225 100644 --- a/src/racket/src/salloc.c +++ b/src/racket/src/salloc.c @@ -105,6 +105,12 @@ THREAD_LOCAL_DECL(static int free_list_bucket_count;) void scheme_set_stack_base(void *base, int no_auto_statics) XFORM_SKIP_PROC { +#if defined(MZ_PLACES_WAITPID) + /* Early, to maximize the chance that no threads have been + created that might later receive SIGCHLD */ + scheme_places_block_child_signal(); +#endif + #ifdef MZ_PRECISE_GC GC_init_type_tags(_scheme_last_type_, scheme_pair_type, scheme_mutable_pair_type, scheme_weak_box_type, @@ -324,6 +330,7 @@ void scheme_set_report_out_of_memory(Scheme_Report_Out_Of_Memory_Proc p) #include # ifdef MZ_PRECISE_GC extern void GC_attach_current_thread_exceptions_to_handler(); +extern void GC_detach_current_thread_exceptions_from_handler(); # endif #endif @@ -372,6 +379,16 @@ void scheme_init_os_thread() XFORM_SKIP_PROC scheme_init_os_thread_like(NULL); } +void scheme_done_os_thread() XFORM_SKIP_PROC +{ + free(scheme_get_thread_local_variables()); +#ifdef OS_X +# ifdef MZ_PRECISE_GC + GC_detach_current_thread_exceptions_from_handler(); +# endif +#endif +} + /************************************************************************/ /* memory utils */ /************************************************************************/ diff --git a/src/racket/src/schminc.h b/src/racket/src/schminc.h index 7f7410c098..d7d0790ba7 100644 --- a/src/racket/src/schminc.h +++ b/src/racket/src/schminc.h @@ -13,7 +13,7 @@ #define USE_COMPILED_STARTUP 1 -#define EXPECTED_PRIM_COUNT 999 +#define EXPECTED_PRIM_COUNT 1000 #define EXPECTED_UNSAFE_COUNT 69 #define EXPECTED_FLFXNUM_COUNT 58 diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h index 7cac749022..fbc7451e4c 100644 --- a/src/racket/src/schpriv.h +++ b/src/racket/src/schpriv.h @@ -313,6 +313,7 @@ void scheme_do_add_global_symbol(Scheme_Env *env, Scheme_Object *sym, void *scheme_get_os_thread_like(); void scheme_init_os_thread_like(void *); +void scheme_done_os_thread(); /*========================================================================*/ /* constants */ @@ -3449,11 +3450,18 @@ typedef struct Scheme_Symbol_Parts { } Scheme_Symbol_Parts; void scheme_spawn_master_place(); -void scheme_places_block_child_signal(); -int scheme_get_child_status(int pid, int *status); -int scheme_places_register_child(int pid, void *signal_fd, int *status); # endif Scheme_Object *scheme_places_deep_copy(Scheme_Object *so); +# ifdef UNIX_PROCESSES +# define MZ_PLACES_WAITPID +void scheme_places_block_child_signal(); +void scheme_places_start_child_signal_handler(); +int scheme_get_child_status(int pid, int is_group, int *status); +int scheme_places_register_child(int pid, int is_group, void *signal_fd, int *status); +void scheme_wait_suspend(); +void scheme_wait_resume(); +void scheme_done_with_process_id(int pid, int is_group); +# endif #endif typedef struct Scheme_Place_Bi_Channel { diff --git a/src/racket/src/schvers.h b/src/racket/src/schvers.h index 71e0536519..fd0ef5c703 100644 --- a/src/racket/src/schvers.h +++ b/src/racket/src/schvers.h @@ -13,12 +13,12 @@ consistently.) */ -#define MZSCHEME_VERSION "5.0.0.6" +#define MZSCHEME_VERSION "5.0.0.7" #define MZSCHEME_VERSION_X 5 #define MZSCHEME_VERSION_Y 0 #define MZSCHEME_VERSION_Z 0 -#define MZSCHEME_VERSION_W 6 +#define MZSCHEME_VERSION_W 7 #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W) diff --git a/src/racket/src/thread.c b/src/racket/src/thread.c index 8c6274f17f..f96e0bfbaa 100644 --- a/src/racket/src/thread.c +++ b/src/racket/src/thread.c @@ -4117,7 +4117,7 @@ void scheme_thread_block(float sleep_time) /* Check scheduled_kills early and often. */ check_scheduled_kills(); -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) /* Reap zombie processes: */ scheme_check_child_done(); #endif @@ -7430,7 +7430,7 @@ static void get_ready_for_GC() #ifdef WINDOWS_PROCESSES scheme_suspend_remembered_threads(); #endif -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) scheme_block_child_signals(1); #endif @@ -7461,7 +7461,7 @@ static void done_with_GC() #ifdef WINDOWS_PROCESSES scheme_resume_remembered_threads(); #endif -#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) +#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID) scheme_block_child_signals(0); #endif