Filing as a security task since the reproduction steps below can be used to crash the jobrunner on any third party wiki using runJobs.php.
Reproduction steps
- Create Module:MemLeakTest with
return { main = function ( f ) local a = 'Paaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' a = a..a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a..a..a a = a..a return a end, -- edit this line to trigger jobs }
- Create MemLeakTest/1 through 9 with {{#invoke:MemLeakTest|main}}
- Run runJobs.php --wait --type=refreshLinks
- Edit Module:MemLeakTest to trigger the jobs
➜ MainContrib git:(main) mwutil run runJobs.php -- --wait --type=refreshLinks
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest table=templatelinks recursive=1 rootJobIsSelf=1 rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1450,timestamp=20260305211229) STARTING
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest table=templatelinks recursive=1 rootJobIsSelf=1 rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1450,timestamp=20260305211229) t=12 good
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"184":[0,"MemLeakTest/9"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1463,timestamp=20260305211229) STARTING
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"184":[0,"MemLeakTest/9"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1463,timestamp=20260305211229) t=268 good
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"180":[0,"MemLeakTest/5"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1459,timestamp=20260305211229) STARTING
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"180":[0,"MemLeakTest/5"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1459,timestamp=20260305211229) t=38 good
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"182":[0,"MemLeakTest/7"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1461,timestamp=20260305211229) STARTING
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"182":[0,"MemLeakTest/7"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1461,timestamp=20260305211229) t=26 good
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"178":[0,"MemLeakTest/3"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1457,timestamp=20260305211229) STARTING
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"178":[0,"MemLeakTest/3"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1457,timestamp=20260305211229) t=32 good
2026-03-05 21:12:29 refreshLinks Module:MemLeakTest pages={"181":[0,"MemLeakTest/6"]} rootJobSignature=394e16ee44bc345d000ce77814c050eb9e356d73 rootJobTimestamp=20260305211229 triggeredRecursive=1 causeAction=edit-page causeAgent=CentralAdmin namespace=828 title=MemLeakTest requestId=bbb9f46d54ed3cca29430242 (id=1460,timestamp=20260305211229) STARTING
PHP Fatal error: Allowed memory size of 157286400 bytes exhausted (tried to allocate 8847385 bytes) in /var/www/html/w/extensions/Scribunto/includes/Engines/LuaSandbox/LuaSandboxInterpreter.php on line 137Cause
There is a memory leak in Scribunto since 47e6d1175363a29ccc3909a3d25b31751699c19a, which changed the logic to use a WeakMap to store the engine objects. The entries are not garbage collected because there is likely a reference cycle somewhere.
Calling ->destroy() manually seems to fix the issue:
public function destroyEngineForParser( Parser $parser ): void {
+ if ( isset( $this->engineForParser[$parser] ) ) {
+ $this->engineForParser[$parser]->destroy();
+ }
+
unset( $this->engineForParser[$parser] );
}Additional information
MW 1.46.0-alpha (d03de87)
PHP 8.3.30 (fpm-fcgi)
LuaSandbox 4.1.3
Lua 5.1.5
Scribunto 723f367