Skip to content

Commit 7b830b7

Browse files
committedAug 29, 2023
Fix std::nothrow aborting when exceptions are disabled (emscripten-core#20132)
1 parent 3a55fe1 commit 7b830b7

File tree

4 files changed

+60
-0
lines changed

4 files changed

+60
-0
lines changed
 

‎system/lib/libcxx/src/new.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,34 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
9090
return p;
9191
}
9292

93+
#if defined(__EMSCRIPTEN__) && defined(_LIBCPP_NO_EXCEPTIONS)
94+
void* _new_nothrow(size_t size) noexcept
95+
{
96+
/// We cannot call ::operator new(size) here because it would abort
97+
/// when malloc returns 0 and exceptions are disabled.
98+
/// Expected behaviour of std::nothrow is not return 0 in that case.
99+
void* p = nullptr;
100+
if (size == 0)
101+
size = 1;
102+
while ((p = ::malloc(size)) == nullptr)
103+
{
104+
std::new_handler nh = std::get_new_handler();
105+
if (nh)
106+
nh();
107+
else
108+
break;
109+
}
110+
return p;
111+
}
112+
#endif
113+
93114
_LIBCPP_WEAK
94115
void*
95116
operator new(size_t size, const std::nothrow_t&) noexcept
96117
{
118+
#if defined(__EMSCRIPTEN__) && defined(_LIBCPP_NO_EXCEPTIONS)
119+
return _new_nothrow(size);
120+
#else
97121
void* p = nullptr;
98122
#ifndef _LIBCPP_NO_EXCEPTIONS
99123
try
@@ -107,6 +131,7 @@ operator new(size_t size, const std::nothrow_t&) noexcept
107131
}
108132
#endif // _LIBCPP_NO_EXCEPTIONS
109133
return p;
134+
#endif // __EMSCRIPTEN__ && _LIBCPP_NO_EXCEPTIONS
110135
}
111136

112137
_LIBCPP_WEAK
@@ -120,6 +145,9 @@ _LIBCPP_WEAK
120145
void*
121146
operator new[](size_t size, const std::nothrow_t&) noexcept
122147
{
148+
#if defined(__EMSCRIPTEN__) && defined(_LIBCPP_NO_EXCEPTIONS)
149+
return _new_nothrow(size);
150+
#else
123151
void* p = nullptr;
124152
#ifndef _LIBCPP_NO_EXCEPTIONS
125153
try
@@ -133,6 +161,7 @@ operator new[](size_t size, const std::nothrow_t&) noexcept
133161
}
134162
#endif // _LIBCPP_NO_EXCEPTIONS
135163
return p;
164+
#endif // __EMSCRIPTEN__ && _LIBCPP_NO_EXCEPTIONS
136165
}
137166

138167
_LIBCPP_WEAK

‎test/core/test_nothrow_new.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2016 The Emscripten Authors. All rights reserved.
2+
// Emscripten is available under two separate licenses, the MIT license and the
3+
// University of Illinois/NCSA Open Source License. Both these licenses can be
4+
// found in the LICENSE file.
5+
6+
#include <iostream>
7+
#include <new>
8+
9+
int main() {
10+
const char* data = new (std::nothrow) char[20 * 1024 * 1024];
11+
if (data == nullptr) {
12+
std::cout << "success" << std::endl;
13+
return 0;
14+
} else {
15+
std::cout << "failure" << std::endl;
16+
return 1;
17+
}
18+
}

‎test/core/test_nothrow_new.out

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
success

‎test/test_core.py

+12
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,18 @@ def test_aborting_new(self, args):
24342434
self.emcc_args += args
24352435
self.do_core_test('test_aborting_new.cpp')
24362436

2437+
@parameterized({
2438+
'nogrow': (['-sABORTING_MALLOC=0'],),
2439+
'grow': (['-sALLOW_MEMORY_GROWTH', '-sMAXIMUM_MEMORY=18MB'],)
2440+
})
2441+
@no_asan('requires more memory when growing')
2442+
@no_lsan('requires more memory when growing')
2443+
@no_4gb('depends on MAXIMUM_MEMORY')
2444+
@no_2gb('depends on MAXIMUM_MEMORY')
2445+
def test_nothrow_new(self, args):
2446+
self.emcc_args += args
2447+
self.do_core_test('test_nothrow_new.cpp')
2448+
24372449
@no_wasm2js('no WebAssembly.Memory()')
24382450
@no_asan('ASan alters the memory size')
24392451
@no_lsan('LSan alters the memory size')

0 commit comments

Comments
 (0)
Please sign in to comment.