Saturday, September 26, 2026
2 changes · 19.0
Enhancements to existing features
This change adds a targeted reproducer showing that importing a newer dependency can reserve a large amount of address space and prevent Odoo's threaded server from starting request threads under the default memory limit. It helps diagnose a reliability issue where imports can cause failures even when actual memory use remains low.
Original PR description
**Reproducer, not meant to be merged as is.** It adds one test and one requirement so runbot shows the failure on its own infrastructure. Description of the issue/feature this PR addresses:…
**Reproducer, not meant to be merged as is.** It adds one test and one requirement so runbot shows the failure on its own infrastructure. Description of the issue/feature this PR addresses: `limit_memory_hard` is applied as `RLIMIT_AS` in [`set_limit_memory_hard()`](https://github.com/odoo/odoo/blob/4e7b84db9455086754164db5e404987c34d48eb7/odoo/service/server.py#L78-L88). `RLIMIT_AS` counts **reserved address space**, not resident memory. A dependency whose allocator reserves a large region up front therefore uses up the budget without using any memory, and the threaded server then fails on the next allocation, most visibly when it starts a request thread. A concrete case: `device_detector` 6.3.0 and later depend on [`yaml-rs`](https://github.com/lava-sh/yaml-rs). Its Linux wheels are built with `--features mimalloc`, which makes mimalloc the Rust global allocator ([`src/lib.rs#L7-L9`](https://github.com/lava-sh/yaml-rs/blob/d060142863228dfeb74bf98070cf81166407dd7e/src/lib.rs#L7-L9), [`Cargo.toml#L54-L61`](https://github.com/lava-sh/yaml-rs/blob/d060142863228dfeb74bf98070cf81166407dd7e/Cargo.toml#L54-L61) at tag 0.1.6). Importing it reserves a 1 GiB arena immediately. Current behavior before PR: The test starts as many threads as fit in 60% of the headroom left under `RLIMIT_AS`, imports `device_detector`, then starts the same number of threads again. Measured locally with this branch, `--workers 0`, and the default `limit_memory_hard` of 2560 MiB: | | VmSize before → after import | Second round of 169 threads | |---|---|---| | `device_detector==6.4.0` | 320 → **1350** MiB | `RuntimeError: can't start new thread` | | `device_detector==6.4.0` + `MIMALLOC_ARENA_RESERVE=131072` | 320 → 390 MiB | OK | | `device_detector==5.0.1` (uses pyyaml) | 320 → 322 MiB | OK | The result is the same on Ubuntu 24.04 / Python 3.12.3 and on Ubuntu 26.04 / Python 3.14.4, so it does not depend on the interpreter's own allocator. On a real test suite with browser tours, the same loss surfaces as `can't start new thread` in `odoo/service/server.py` and as `MemoryError` in unrelated places, depending on which allocation hits the ceiling first. Desired behavior after PR is merged: Importing a dependency that reserves address space it does not use should not leave the server unable to start threads under the default `limit_memory_hard`. The server already handles this class of problem for glibc: before starting the threaded server it calls [`mallopt(M_ARENA_MAX, 2)`](https://github.com/odoo/odoo/blob/4e7b84db9455086754164db5e404987c34d48eb7/odoo/service/server.py#L1638-L1660), because, in its own words, "a downside of creating one arena per cpu core is the increase of virtual memory which Odoo is based upon in order to limit the memory usage for threaded workers". Nothing covers an allocator embedded in a dependency. Two options that would cover it: - setting `MIMALLOC_ARENA_RESERVE` (or an equivalent cap) when it is not already set, mirroring the existing `MALLOC_ARENA_MAX` handling; - enforcing the hard limit on resident memory rather than on `RLIMIT_AS` for the threaded server. We are working around it downstream today with `MIMALLOC_ARENA_RESERVE=131072` in our base image, and would rather not need that. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Endpoint checks now avoid using the French business directory for non-French partners, even when they have French-style company identifiers. This prevents unnecessary or incorrect validation steps and helps international e-invoicing setup work more smoothly.
Original PR description
for non-french partners, a check on the annuaire shouldnt happen when checking their endpoints, even if they have a siren/siret related-task-id-6327357 Forward-Port-Of: odoo/odoo#289626