Re: A fix for SBCL error "thread local storage exhausted" when creating too many rules

Gunter K�nigsmann via Maxima-discuss <[email protected]> Sun, 07 Jun 2026 11:15:49 +0200
Newsgroups gmane.comp.mathematics.maxima.general
Message-ID <[email protected]>
A mutex would protect the assumptions database from being modified while reading from it. But if a thread would want to make its own assumptions the new code would require that thread to introduce another step and create it's own context, somehow, that isn't shared with that other thread. 
Not that threads in Maxima would b a thing, right now... 

On 7 June 2026 11:01:13 CEST, David Scherfgen <[email protected]> wrote:
>Hi Gunter,
>
>If we ever try to make Maxima thread-safe, then we need to protect the
>access to *rule-symbol-pool* using a mutex.
>To be honest, I doubt that'll happen, though. There's so much "global
>state" in Maxima that's shared between threads.
>
>Best regards
>David
>
>Am So., 7. Juni 2026 um 10:56 Uhr schrieb Gunter K�nigsmann <
>[email protected]>:
>
>> My only question would be: if we ever introduce multi-threaded work... ...
>> as far as I understand stuff stored in thread-local memory won't be shared
>> between threads so each thread could make its own assumptions without
>> having to fea race conditions.
>>
>> Didn't look closely enough at the new code to see if the new code would
>> allow that, as well.
>>
>> Having said that I hate running out of thread-local memory as it normally
>> is a clear game over situation.
>>
>> Kind regards,
>>
>>    Gunter.
>>
>>
>> On 5 June 2026 15:57:21 CEST, David Scherfgen via Maxima-discuss <
>> [email protected]> wrote:
>>
>>> Hi everyone,
>>>
>>> I've been looking into the annoying bug #4517
>>> <https://sourceforge.net/p/maxima/bugs/4517/>, where Maxima crashes on
>>> SBCL due to Thread-Local Storage (TLS) exhaustion after repeatedly
>>> generating and destroying rules (via defrule, tellsimp, etc.). It
>>> famously can be triggered by running the rtest_rules test a few times.
>>>
>>> The root cause is that the pattern-matching compiler dynamically binds
>>> new symbols generated during rule creation. On SBCL, every newly
>>> dynamically bound special variable permanently consumes a TLS slot. Even if
>>> the rule is subsequently removed, SBCL cannot free the underlying TLS
>>> index, eventually causing a hard crash once the limit is reached.
>>>
>>> To resolve this, I've implemented a reusable symbol pool (
>>> *rule-symbol-pool*). The patch modifies matcom.lisp to track all symbols
>>> generated for a specific rule via its property list. When a rule is
>>> overwritten, or when it is destroyed via kill1-atom in suprv1.lisp,
>>> those symbols are completely scrubbed (makunbound, fmakunbound, and
>>> property list cleared) and pushed back into the pool for the next rule to
>>> recycle. Now, the TLS consumption strictly depends on the rules that exist
>>> at the same time, rather than all rules ever created over the lifetime of
>>> the session.
>>>
>>> I'd love to get some feedback on this approach, and I have a specific
>>> question for the veterans regarding the historical design: In my patch, I
>>> replaced the tr-gensym call in genref with the new pool allocator (
>>> get-rule-symbol). Does anyone recall the original rationale for using
>>> tr-gensym (which interns the symbol) in genref instead of a standard
>>> uninterned gensym, as it is the case in other places in the relevant
>>> code? I want to ensure I'm not breaking a subtle dependency with the
>>> translator.
>>>
>>> Note: A visible side effect of this change is that these match variables
>>> will now be named RULE-SYMBOL-... rather than TR-GENSYM~... in
>>> macro-expanded code.
>>>
>>> Best regards
>>> David Scherfgen
>>>
>>

_______________________________________________
Maxima-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/maxima-discuss