Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nodejs start fails with std::bad_alloc #4156

Closed
kasbert opened this issue May 9, 2023 · 6 comments
Closed

Nodejs start fails with std::bad_alloc #4156

kasbert opened this issue May 9, 2023 · 6 comments

Comments

@kasbert
Copy link

kasbert commented May 9, 2023

Details

node start fails always with std::bad_alloc.
This is a emulated virtual machine, so the problem probably lies there, but maybe you could help somehow.

I have a macOS on M1 Arm silicon and I am running emulated x86_64 Debian Linux guest on Qemu. There is 4GB memory on VM and the node process does not allocate much. I tried with node versions 10-18.

$ gdb node
(gdb) r --max_old_space_size=3000
Starting program: /usr/bin/node --max_old_space_size=3000
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff329d700 (LWP 2500)]
[New Thread 0x7ffff2a9c700 (LWP 2501)]
[New Thread 0x7ffff229b700 (LWP 2502)]
[New Thread 0x7ffff1a9a700 (LWP 2503)]
[New Thread 0x7ffff1299700 (LWP 2504)]
[New Thread 0x7ffff0a98700 (LWP 2505)]
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

Thread 1 "node" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) where
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff5b01537 in __GI_abort () at abort.c:79
#2  0x00007ffff4ffb7ec in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff5006966 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff50069d1 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff5006c65 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff4ffdf0f in std::__throw_bad_alloc() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff68136e1 in ?? () from /lib/x86_64-linux-gnu/libnode.so.72
#8  0x00007ffff6819603 in v8::internal::Heap::ProcessPretenuringFeedback() () from /lib/x86_64-linux-gnu/libnode.so.72
#9  0x00007ffff682de47 in v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) ()
   from /lib/x86_64-linux-gnu/libnode.so.72
#10 0x00007ffff682ec96 in v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) ()
   from /lib/x86_64-linux-gnu/libnode.so.72
#11 0x00007ffff6830e1c in v8::internal::Heap::AllocateRawWithLightRetry(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::Allocatio/
#12 0x00007ffff6830e84 in v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::Allocati/
#13 0x00007ffff67f73af in v8::internal::Factory::AllocateRawArray(int, v8::internal::AllocationType) () from /lib/x86_64-linux-gnu/libnode.so.72
#14 0x00007ffff67f7828 in v8::internal::Factory::NewFixedArrayWithFiller(v8::internal::RootIndex, int, v8::internal::Object, v8::internal::AllocationType) ()
   from /lib/x86_64-linux-gnu/libnode.so.72
#15 0x00007ffff6a2bf33 in v8::internal::BaseNameDictionary<v8::internal::GlobalDictionary, v8::internal::GlobalDictionaryShape>::CollectKeysTo(v8::internal::Handl/
#16 0x00007ffff69e5a4c in v8::internal::KeyAccumulator::CollectOwnPropertyNames(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal:/
#17 0x00007ffff69e5cde in v8::internal::KeyAccumulator::CollectOwnKeys(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal::JSObject/
#18 0x00007ffff69e69f3 in v8::internal::KeyAccumulator::CollectKeys(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal::JSReceiver>/
#19 0x00007ffff69e6b85 in v8::internal::FastKeyAccumulator::GetKeysSlow(v8::internal::GetKeysConversion) () from /lib/x86_64-linux-gnu/libnode.so.72
#20 0x00007ffff69e6c6d in v8::internal::KeyAccumulator::GetKeys(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::KeyCollectionMode, v8::internal::Pro/
#21 0x00007ffff6b3f597 in v8::internal::Runtime_ObjectGetOwnPropertyNames(int, unsigned long*, v8::internal::Isolate*) () from /lib/x86_64-linux-gnu/libnode.so.72
#22 0x00007ffff70e8d99 in ?? () from /lib/x86_64-linux-gnu/libnode.so.72
#23 0x00007fffffffd638 in ?? ()
#24 0x00007fffffffd5c0 in ?? ()
#25 0x0000000000000006 in ?? ()
#26 0x00007fffffffd628 in ?? ()
#27 0x00007ffff70b7f08 in ?? () from /lib/x86_64-linux-gnu/libnode.so.72
#28 0x00002537fa0802f9 in ?? ()
#29 0x00007fffffffd628 in ?? ()
#30 0x00002335c8382211 in ?? ()
#31 0x000018be47d4d299 in ?? ()
#32 0x00000000000000fc in ?? ()
#33 0x0000000000000001 in ?? ()
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) 
[1]+  Stopped                 gdb node
jarkkosonninen@lima-debian:/$ ps axu |grep node
jarkkos+    2472  8.5  3.4 450632 139688 pts/0   Tl   06:10   0:25 gdb node
jarkkos+    2499  0.7  0.7 583644 30500 pts/0    tl   06:14   0:00 /usr/bin/node --max_old_space_size=3000
jarkkosonninen@lima-debian:/$ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       187Mi       2.4Gi       4.0Mi       1.3Gi       3.4Gi
Swap:             0B          0B          0B

Node.js version

$ node -v
v12.22.12

Example code

No response

Operating system

$ uname -a
Linux lima-debian 5.10.0-22-amd64 #1 SMP Debian 5.10.178-3 (2023-04-22) x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 11 (bullseye)
Release:	11
Codename:	bullseye

/opt/homebrew/bin/qemu-system-x86_64 -m 4096 -cpu qemu64 -machine q35,vmport=off -accel tcg,thread=multi,tb-size=512 -global ICH9-LPC.disable_s3=1 -smp 4,sockets=1,cores=4,threads=1 -drive if=pflash,format=raw,readonly=on,file=/opt/homebrew/share/qemu/edk2-x86_64-code.fd -boot order=c,splash-time=0,menu=on -drive file=/Users/jarkkosonninen/.lima/debian/diffdisk,if=virtio,discard=on -drive id=cdrom0,if=none,format=raw,readonly=on,file=/Users/jarkkosonninen/.lima/debian/cidata.iso -device virtio-scsi-pci,id=scsi0 -device scsi-cd,bus=scsi0.0,drive=cdrom0 -netdev user,id=net0,net=192.168.5.0/24,dhcpstart=192.168.5.15,hostfwd=tcp:127.0.0.1:51391-:22 -device virtio-net-pci,netdev=net0,mac=52:55:55:c6:37:29 -device virtio-rng-pci -display none -device virtio-vga -device virtio-keyboard-pci -device virtio-mouse-pci -device qemu-xhci,id=usb-bus -parallel none -chardev socket,id=char-serial,path=/Users/jarkkosonninen/.lima/debian/serial.sock,server=on,wait=off,logfile=/Users/jarkkosonninen/.lima/debian/serial.log -serial chardev:char-serial -chardev socket,id=char-qmp,path=/Users/jarkkosonninen/.lima/debian/qmp.sock,server=on,wait=off -qmp chardev:char-qmp -name lima-debian -pidfile /Users/jarkkosonninen/.lima/debian/qemu.pid

Scope

runtime

Module and version

Not applicable.

@preveen-stack
Copy link
Contributor

can you try it without the --max_old_space_size argument and see

@kasbert
Copy link
Author

kasbert commented May 13, 2023

Same result
$ node
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted

If I run Ubuntu 22.04 in a container and install nodejs, it works. As Ubuntu has it's own binaries, it must be some compile option or patch, which makes it work.

@preveen-stack
Copy link
Contributor

#include <iostream>

int main() {
    for (int i = 1; i <=6 ; i++) {
        try {
            size_t size = i * 512 * 1024 * 1024;  // 512MB, 1GB, 1.5GB, 2GB, 2.5GB, 3GB
            std::cout << "Trying to allocate " << size << " bytes of memory " << std::endl;
            int* arr = new int[size];
            std::cout << "Successfully allocated " << size << " bytes of memory." << std::endl;
            delete[] arr;
        }
        catch (const std::bad_alloc& e) {
            std::cerr << "Memory allocation failed: " << e.what() << std::endl;
        }
    }
    return 0;
}
$ g++ -g -o mem_alloc_test mem_alloc_test.cpp

Is it possible that you can try the above code on your setup

@kasbert
Copy link
Author

kasbert commented May 14, 2023

$ ./mem_alloc_test

Trying to allocate 536870912 bytes of memory 
Successfully allocated 536870912 bytes of memory.
Trying to allocate 1073741824 bytes of memory 
Memory allocation failed: std::bad_alloc
Trying to allocate 1610612736 bytes of memory 
Memory allocation failed: std::bad_alloc
Trying to allocate 18446744071562067968 bytes of memory 
Memory allocation failed: std::bad_array_new_length
Trying to allocate 18446744072098938880 bytes of memory 
Memory allocation failed: std::bad_array_new_length
Trying to allocate 18446744072635809792 bytes of memory 
Memory allocation failed: std::bad_array_new_length

I changed the test program int[] to char[] and "int i" to "long i" and got

$ ./mem_alloc_test 
Trying to allocate 536870912 bytes of memory 
Successfully allocated 536870912 bytes of memory.
Trying to allocate 1073741824 bytes of memory 
Successfully allocated 1073741824 bytes of memory.
Trying to allocate 1610612736 bytes of memory 
Successfully allocated 1610612736 bytes of memory.
Trying to allocate 2147483648 bytes of memory 
Successfully allocated 2147483648 bytes of memory.
Trying to allocate 2684354560 bytes of memory 
Successfully allocated 2684354560 bytes of memory.
Trying to allocate 3221225472 bytes of memory 
Successfully allocated 3221225472 bytes of memory.

Changing /proc/sys/vm/overcommit_memory did not make any difference. I got the same results with ubuntu container.
Ulimit:

$ ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 15533
max locked memory           (kbytes, -l) 501627
max memory size             (kbytes, -m) unlimited
open files                          (-n) 1024
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 15533
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited

@kasbert
Copy link
Author

kasbert commented May 30, 2023

Seems that v8.10.0 broke it

root@78a9b14980d6:~# nvm install v8.9.4
v8.9.4 is already installed.
Now using node v8.9.4 (npm v5.6.0)
root@78a9b14980d6:~# node 
> 
root@78a9b14980d6:~# nvm install v8.10.0
v8.10.0 is already installed.
Now using node v8.10.0 (npm v)
root@78a9b14980d6:~# node 
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

@kasbert
Copy link
Author

kasbert commented Oct 4, 2023

This seem to have resolved by itself.
Could be some macOS update or new qemu 8.1.1 or phase of the moon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants