Skip to content

Wasm doesn't work in limited virtual memory situations #56596

@emspishak

Description

@emspishak

Version

v22.13.0

Platform

Linux weborigin002 6.1.0-26-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.112-1 (2024-09-30) x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

  1. ulimit -v 2097152
  2. node -e "await fetch('https://www.google.com')"

How often does it reproduce? Is there a required condition?

Everytime, no required conditions.

What is the expected behavior? Why is that the expected behavior?

I expect the fetch to succeed.

What do you see instead?

The fetch fails with the error:

node:internal/deps/undici/undici:5822
      return await WebAssembly.instantiate(mod, {
                               ^

RangeError: WebAssembly.instantiate(): Out of memory: Cannot allocate Wasm memory for new instance
    at lazyllhttp (node:internal/deps/undici/undici:5822:32)

Node.js v22.13.0

Additional information

I would like to run a Node server on a shared webhost, which has per-user memory limitations to prevent one (or multiple) users from consuming too much memory. The configuration they use is ulimit -v 2097152 to limit virtual memory to about 2GB. Node Wasm seems to allocate around 10GB of virtual memory, which fails when memory is limited in this way. 2GB seems like a reasonable amount of memory and it seems like Node should support it. I asked my hosting provider if they could bump up the memory limit and they said they don't want to.

I started looking through the code for this, starting at

MaybeHandle<WasmMemoryObject> maybe_memory_object = WasmMemoryObject::New(

I found the --wasm_max_mem_pages command line flag, but even with --wasm_max_mem_pages=2 it still tries to allocate 10GB.

It appears to be the reservation_size at

size_t reservation_size =
that ends up being 10GB. That looks like it's coming from
return kFullGuardSize32;
where it just always returns 10GB.

So it seems like maybe there it could detect how much memory is available and base the amount it returns off that (some percentage of it so it keeps free memory for other things too?). I'm happy to send a PR for this but would appreciate some help figuring out how this should work.

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions