GsDevKit / GsDevKit_home

master GsDevKit project
http://gsdevkit.github.io/GsDevKit_home
MIT License
31 stars 36 forks source link

RxMatcher string size is limited by stack limit #333

Closed Rinzwind closed 4 months ago

Rinzwind commented 4 months ago

The matching of an RxMatcher uses a recursive implementation so the size of the string that can be matched is limited by the stack limit as demonstrated by the example in the Dockerfile given below:

$ image=$(docker build -q .) && docker run $image
[…]
topaz 1> printit
    System stackLimit
%
1234
topaz 1> doit
    | strings matcher |
    strings := (0 to: 2000 by: 100) collect: [ :n | String new: n withAll: $_ ].
    matcher := RxMatcher forString: '.*'.
    strings do: [ :string |
        matcher matches: string.
        Transcript show: System stackDepthHighwater ]
%
--transcript--38
--transcript--190
[…]
--transcript--2448
--transcript--2621
--transcript--2795
[…]
Stack overflow,  Stack depth 3256 
topaz 1> where
==> 1 AlmostOutOfStack (AbstractException) >> _signalFromPrimitive: @24 line 26
2 [] in RxMatcher >> syntaxAny                  @5 line 6
3 RxmPredicate >> matchAgainst:                 @9 line 8
4 RxmBranch >> matchAgainst:                    @2 line 4
[…]
3245 RxmPredicate >> matchAgainst:                 @11 line 9
3246 RxmBranch >> matchAgainst:                    @2 line 4
3247 RxmBranch >> matchAgainst:                    @2 line 4
3248 RxmMarker >> matchAgainst:                    @5 line 7
3249 RxMatcher >> tryMatch                         @17 line 10
[…]
3255 Executed Code                                 @8 line 4
3256 GsNMethod class >> _gsReturnToC               @1 line 1
topaz 1> exit
[…]

Avoiding that would presumably require transforming RxMatcher to keep its own stack. One can increase the stack limit, but doing so only for RxMatcher’s sake may not be desirable in all applications, and there’s a maximum limit as well: 1000000 per the documentation on GEM_MAX_SMALLTALK_STACK_DEPTH for GemStone/S v3.4, or just 30000 for native code on an Intel CPU per the documentation for GemStone/S v3.7.

A question I have myself regarding the example is how it is that the AlmostOutOfStack occurs only at a stack depth of 3256 while GEM_MAX_SMALLTALK_STACK_DEPTH is set to 1234. I guess the explanation is in the documentation’s mention of it being an ‘approximate number’ but it’s not quite clear to me.

Dockerfile:

FROM ubuntu:20.04
COPY <<"EOF" /home/gsuser/example
    login
    printit
        System stackLimit
    %
    doit
        | strings matcher |
        strings := (0 to: 2000 by: 100) collect: [ :n | String new: n withAll: $_ ].
        matcher := RxMatcher forString: '.*'.
        strings do: [ :string |
            matcher matches: string.
            Transcript show: System stackDepthHighwater ]
    %
    where
    exit
EOF
COPY <<"EOF" /home/gsuser/runExample
    cd ~/GsDevKit_home &&
    . bin/defHOME_PATH.env &&
    startStone devKit_343 &&
    sed $'s/^\t//' <~/example | \
        startTopaz devKit_343 -l -C GEM_MAX_SMALLTALK_STACK_DEPTH=1234
EOF
COPY <<"EOF" /home/gsuser/installGS
    git -C ~ clone --depth 1 https://github.com/GsDevKit/GsDevKit_home.git &&
    cd ~/GsDevKit_home &&
    . bin/defHOME_PATH.env &&
    installServerClient &&
    createStone devKit_343 3.4.3 &&
    createClient tode1
EOF
COPY <<"EOF" /root/setup
    apt-get update &&
    DEBIAN_FRONTEND=noninteractive apt-get --assume-yes install \
        sudo tzdata lsb-release git &&
    apt-get clean &&
    useradd gsuser &&
    chown --recursive gsuser ~gsuser &&
    echo 'gsuser ALL=(ALL) NOPASSWD:ALL' >/etc/sudoers.d/gsuser
EOF
RUN bash /root/setup
RUN sudo --user gsuser bash /home/gsuser/installGS
CMD sudo --user gsuser bash /home/gsuser/runExample
dalehenrich commented 4 months ago

@Rinzwind, Thanks for your interest.

Regarding the stack overflow behavior, that is best reported/discussed on the GemStone-Smalltalk mailing list.

... and the RxMatcher is actually part of the glassdb/glass project, so if you have improvements to RxMatcher please submit a PR with your improvements as well as tests to that project and if the CI tests pass it will be integrated for all to use ...

Thanks!