koffi 2.6.2 → 2.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -1
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm32hf/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_riscv64hf64/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/contribute.md +1 -1
- package/doc/packaging.md +5 -3
- package/index.js +3 -3
- package/indirect.js +3 -3
- package/package.json +3 -3
- package/src/core/libcc/libcc.cc +260 -176
- package/src/core/libcc/libcc.hh +31 -19
- package/src/koffi/CMakeLists.txt +9 -9
- package/src/koffi/src/ffi.cc +2 -2
- package/src/koffi/src/win32.cc +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,10 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
### Koffi 2.6
|
|
6
6
|
|
|
7
|
-
#### Koffi 2.6.
|
|
7
|
+
#### Koffi 2.6.4 (2023-10-26)
|
|
8
|
+
|
|
9
|
+
- Fix build issue with recent Visual Studio versions
|
|
10
|
+
|
|
11
|
+
#### Koffi 2.6.3 (2023-10-17)
|
|
8
12
|
|
|
9
13
|
- Add indirect loading script to help some bundlers
|
|
10
14
|
|
|
15
|
+
```{warning}
|
|
16
|
+
Pre-built binaries don't work correctly in Koffi 2.6.2, skip this version.
|
|
17
|
+
```
|
|
18
|
+
|
|
11
19
|
#### Koffi 2.6.1 (2023-09-18)
|
|
12
20
|
|
|
13
21
|
- Support string direction qualifiers in classic function definitions
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/doc/contribute.md
CHANGED
package/doc/packaging.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Bundlers and Koffi
|
|
2
2
|
|
|
3
|
-
## Bundling
|
|
3
|
+
## Bundling
|
|
4
|
+
|
|
5
|
+
### Native modules
|
|
4
6
|
|
|
5
7
|
*Simplified in Koffi 2.5.9*
|
|
6
8
|
|
|
@@ -36,13 +38,13 @@ resources/
|
|
|
36
38
|
MyApp.exe
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
### Indirect loader
|
|
40
42
|
|
|
41
43
|
*New in Koffi 2.6.2*
|
|
42
44
|
|
|
43
45
|
Some bundlers (such as vite) don't like when require is used with native modules.
|
|
44
46
|
|
|
45
|
-
In this case, you can use `
|
|
47
|
+
In this case, you can use `require('koffi/indirect')` but you will need to make sure that the native Koffi modules are packaged properly.
|
|
46
48
|
|
|
47
49
|
## Packaging examples
|
|
48
50
|
|
package/index.js
CHANGED
|
@@ -378,8 +378,8 @@ var require_package = __commonJS({
|
|
|
378
378
|
"build/dist/src/koffi/package.json"(exports2, module2) {
|
|
379
379
|
module2.exports = {
|
|
380
380
|
name: "koffi",
|
|
381
|
-
version: "2.6.
|
|
382
|
-
stable: "2.6.
|
|
381
|
+
version: "2.6.4",
|
|
382
|
+
stable: "2.6.4",
|
|
383
383
|
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
384
384
|
keywords: [
|
|
385
385
|
"foreign",
|
|
@@ -424,7 +424,7 @@ var require_package = __commonJS({
|
|
|
424
424
|
cnoke: {
|
|
425
425
|
output: "build/koffi/{{ platform }}_{{ arch }}",
|
|
426
426
|
napi: 8,
|
|
427
|
-
require: "./
|
|
427
|
+
require: "./index.js"
|
|
428
428
|
}
|
|
429
429
|
};
|
|
430
430
|
}
|
package/indirect.js
CHANGED
|
@@ -378,8 +378,8 @@ var require_package = __commonJS({
|
|
|
378
378
|
"build/dist/src/koffi/package.json"(exports2, module2) {
|
|
379
379
|
module2.exports = {
|
|
380
380
|
name: "koffi",
|
|
381
|
-
version: "2.6.
|
|
382
|
-
stable: "2.6.
|
|
381
|
+
version: "2.6.4",
|
|
382
|
+
stable: "2.6.4",
|
|
383
383
|
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
384
384
|
keywords: [
|
|
385
385
|
"foreign",
|
|
@@ -424,7 +424,7 @@ var require_package = __commonJS({
|
|
|
424
424
|
cnoke: {
|
|
425
425
|
output: "build/koffi/{{ platform }}_{{ arch }}",
|
|
426
426
|
napi: 8,
|
|
427
|
-
require: "./
|
|
427
|
+
require: "./index.js"
|
|
428
428
|
}
|
|
429
429
|
};
|
|
430
430
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koffi",
|
|
3
|
-
"version": "2.6.
|
|
4
|
-
"stable": "2.6.
|
|
3
|
+
"version": "2.6.4",
|
|
4
|
+
"stable": "2.6.4",
|
|
5
5
|
"description": "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"foreign",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"cnoke": {
|
|
32
32
|
"output": "build/koffi/{{ platform }}_{{ arch }}",
|
|
33
33
|
"napi": 8,
|
|
34
|
-
"require": "./
|
|
34
|
+
"require": "./index.js"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/core/libcc/libcc.cc
CHANGED
|
@@ -789,10 +789,12 @@ bool ParseBool(Span<const char> str, bool *out_value, unsigned int flags,
|
|
|
789
789
|
TRY_MATCH("1", true);
|
|
790
790
|
TRY_MATCH("On", true);
|
|
791
791
|
TRY_MATCH("Y", true);
|
|
792
|
+
TRY_MATCH("Yes", true);
|
|
792
793
|
TRY_MATCH("True", true);
|
|
793
794
|
TRY_MATCH("0", false);
|
|
794
795
|
TRY_MATCH("Off", false);
|
|
795
796
|
TRY_MATCH("N", false);
|
|
797
|
+
TRY_MATCH("No", false);
|
|
796
798
|
TRY_MATCH("False", false);
|
|
797
799
|
|
|
798
800
|
if (flags & (int)ParseFlag::Log) {
|
|
@@ -1424,7 +1426,7 @@ static inline void ProcessArg(const FmtArg &arg, AppendFunc append)
|
|
|
1424
1426
|
RG_ASSERT(arg.u.random.len <= RG_SIZE(out_buf.data));
|
|
1425
1427
|
|
|
1426
1428
|
for (Size j = 0; j < arg.u.random.len; j++) {
|
|
1427
|
-
int rnd =
|
|
1429
|
+
int rnd = GetRandomIntFast(0, (int)chars.len);
|
|
1428
1430
|
out_buf.Append(chars[rnd]);
|
|
1429
1431
|
}
|
|
1430
1432
|
|
|
@@ -2144,37 +2146,6 @@ fail:
|
|
|
2144
2146
|
return str_buf;
|
|
2145
2147
|
}
|
|
2146
2148
|
|
|
2147
|
-
void SetEnvironmentVar(const char *name, const char *value)
|
|
2148
|
-
{
|
|
2149
|
-
RG_ASSERT(name && name[0] && !strchr(name, '='));
|
|
2150
|
-
RG_ASSERT(value);
|
|
2151
|
-
|
|
2152
|
-
if (win32_utf8) {
|
|
2153
|
-
RG_CRITICAL(SetEnvironmentVariableA(name, value), "Failed to set environment variable '%1' to '%2': %3", name, value, GetWin32ErrorString());
|
|
2154
|
-
} else {
|
|
2155
|
-
wchar_t name_w[256];
|
|
2156
|
-
wchar_t value_w[4096];
|
|
2157
|
-
|
|
2158
|
-
RG_CRITICAL(ConvertUtf8ToWin32Wide(name, name_w) >= 0, "Failed to set environment variable '%1' to '%2'", name, value);
|
|
2159
|
-
RG_CRITICAL(ConvertUtf8ToWin32Wide(value, value_w) >= 0, "Failed to set environment variable '%1' to '%2'", name, value);
|
|
2160
|
-
RG_CRITICAL(SetEnvironmentVariableW(name_w, value_w), "Failed to set environment variable '%1' to '%2': %3", name, value, GetWin32ErrorString());
|
|
2161
|
-
}
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
|
-
void DeleteEnvironmentVar(const char *name)
|
|
2165
|
-
{
|
|
2166
|
-
RG_ASSERT(name && name[0] && !strchr(name, '='));
|
|
2167
|
-
|
|
2168
|
-
if (win32_utf8) {
|
|
2169
|
-
RG_CRITICAL(SetEnvironmentVariableA(name, nullptr), "Failed to clear environment variable '%1': %2", name, GetWin32ErrorString());
|
|
2170
|
-
} else {
|
|
2171
|
-
wchar_t name_w[256];
|
|
2172
|
-
|
|
2173
|
-
RG_CRITICAL(ConvertUtf8ToWin32Wide(name, name_w) >= 0, "Failed to clear environment variable '%1'", name);
|
|
2174
|
-
RG_CRITICAL(SetEnvironmentVariableW(name_w, nullptr), "Failed to clear environment variable '%1': %2", name, GetWin32ErrorString());
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
2149
|
static FileType FileAttributesToType(uint32_t attr)
|
|
2179
2150
|
{
|
|
2180
2151
|
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
|
|
@@ -2358,20 +2329,6 @@ EnumResult EnumerateDirectory(const char *dirname, const char *filter, Size max_
|
|
|
2358
2329
|
|
|
2359
2330
|
#else
|
|
2360
2331
|
|
|
2361
|
-
void SetEnvironmentVar(const char *name, const char *value)
|
|
2362
|
-
{
|
|
2363
|
-
RG_ASSERT(name && name[0] && !strchr(name, '='));
|
|
2364
|
-
RG_ASSERT(value);
|
|
2365
|
-
|
|
2366
|
-
RG_CRITICAL(!setenv(name, value, 1), "Failed to set environment variable '%1' to '%2': %3", name, value, strerror(errno));
|
|
2367
|
-
}
|
|
2368
|
-
|
|
2369
|
-
void DeleteEnvironmentVar(const char *name)
|
|
2370
|
-
{
|
|
2371
|
-
RG_ASSERT(name && name[0] && !strchr(name, '='));
|
|
2372
|
-
RG_CRITICAL(!unsetenv(name), "Failed to clear environment variable '%1': %2", name, strerror(errno));
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2375
2332
|
static FileType FileModeToType(mode_t mode)
|
|
2376
2333
|
{
|
|
2377
2334
|
if (S_ISDIR(mode)) {
|
|
@@ -3917,7 +3874,7 @@ struct PendingIO {
|
|
|
3917
3874
|
}
|
|
3918
3875
|
};
|
|
3919
3876
|
|
|
3920
|
-
bool ExecuteCommandLine(const char *cmd_line, const
|
|
3877
|
+
bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
3921
3878
|
FunctionRef<Span<const uint8_t>()> in_func,
|
|
3922
3879
|
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code)
|
|
3923
3880
|
{
|
|
@@ -3932,9 +3889,9 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
3932
3889
|
|
|
3933
3890
|
// Convert work directory
|
|
3934
3891
|
Span<wchar_t> work_dir_w;
|
|
3935
|
-
if (work_dir) {
|
|
3936
|
-
work_dir_w = AllocateSpan<wchar_t>(&temp_alloc, 2 * strlen(work_dir) + 1);
|
|
3937
|
-
if (ConvertUtf8ToWin32Wide(work_dir, work_dir_w) < 0)
|
|
3892
|
+
if (info.work_dir) {
|
|
3893
|
+
work_dir_w = AllocateSpan<wchar_t>(&temp_alloc, 2 * strlen(info.work_dir) + 1);
|
|
3894
|
+
if (ConvertUtf8ToWin32Wide(info.work_dir, work_dir_w) < 0)
|
|
3938
3895
|
return false;
|
|
3939
3896
|
} else {
|
|
3940
3897
|
work_dir_w = {};
|
|
@@ -3986,6 +3943,45 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
3986
3943
|
if (out_func.IsValid() && !CreateOverlappedPipe(true, false, PipeMode::Byte, out_pipe))
|
|
3987
3944
|
return false;
|
|
3988
3945
|
|
|
3946
|
+
// Prepare environment (if needed)
|
|
3947
|
+
HeapArray<wchar_t> new_env_w;
|
|
3948
|
+
if (info.reset_env || info.env_variables.len) {
|
|
3949
|
+
if (!info.reset_env) {
|
|
3950
|
+
Span<wchar_t> current_env = MakeSpan(GetEnvironmentStringsW(), 0);
|
|
3951
|
+
|
|
3952
|
+
do {
|
|
3953
|
+
Size len = (Size)wcslen(current_env.end());
|
|
3954
|
+
current_env.len += len + 1;
|
|
3955
|
+
} while (current_env.ptr[current_env.len]);
|
|
3956
|
+
|
|
3957
|
+
new_env_w.Append(current_env);
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3960
|
+
for (const ExecuteInfo::KeyValue &kv: info.env_variables) {
|
|
3961
|
+
Span<const char> key = kv.key;
|
|
3962
|
+
Span<const char> value = kv.value;
|
|
3963
|
+
|
|
3964
|
+
Size len = 2 * (key.len + value.len + 1) + 1;
|
|
3965
|
+
new_env_w.Reserve(len);
|
|
3966
|
+
|
|
3967
|
+
len = ConvertUtf8ToWin32Wide(key, new_env_w.TakeAvailable());
|
|
3968
|
+
if (len < 0) [[unlikely]]
|
|
3969
|
+
return false;
|
|
3970
|
+
new_env_w.len += len;
|
|
3971
|
+
|
|
3972
|
+
new_env_w.Append(L'=');
|
|
3973
|
+
|
|
3974
|
+
len = ConvertUtf8ToWin32Wide(value, new_env_w.TakeAvailable());
|
|
3975
|
+
if (len < 0) [[unlikely]]
|
|
3976
|
+
return false;
|
|
3977
|
+
new_env_w.len += len;
|
|
3978
|
+
|
|
3979
|
+
new_env_w.Append(0);
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
new_env_w.Append(0);
|
|
3983
|
+
}
|
|
3984
|
+
|
|
3989
3985
|
// Start process
|
|
3990
3986
|
HANDLE process_handle;
|
|
3991
3987
|
{
|
|
@@ -4010,9 +4006,11 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
4010
4006
|
si.dwFlags |= STARTF_USESTDHANDLES;
|
|
4011
4007
|
}
|
|
4012
4008
|
|
|
4009
|
+
int flags = CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT;
|
|
4010
|
+
|
|
4013
4011
|
PROCESS_INFORMATION pi = {};
|
|
4014
|
-
if (!CreateProcessW(nullptr, cmd_line_w.ptr, nullptr, nullptr, TRUE,
|
|
4015
|
-
|
|
4012
|
+
if (!CreateProcessW(nullptr, cmd_line_w.ptr, nullptr, nullptr, TRUE, flags,
|
|
4013
|
+
new_env_w.ptr, work_dir_w.ptr, &si, &pi)) {
|
|
4016
4014
|
LogError("Failed to start process: %1", GetWin32ErrorString());
|
|
4017
4015
|
return false;
|
|
4018
4016
|
}
|
|
@@ -4221,10 +4219,12 @@ void CloseDescriptorSafe(int *fd_ptr)
|
|
|
4221
4219
|
*fd_ptr = -1;
|
|
4222
4220
|
}
|
|
4223
4221
|
|
|
4224
|
-
bool ExecuteCommandLine(const char *cmd_line, const
|
|
4222
|
+
bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4225
4223
|
FunctionRef<Span<const uint8_t>()> in_func,
|
|
4226
4224
|
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code)
|
|
4227
4225
|
{
|
|
4226
|
+
BlockAllocator temp_alloc;
|
|
4227
|
+
|
|
4228
4228
|
// Create read pipes
|
|
4229
4229
|
int in_pfd[2] = {-1, -1};
|
|
4230
4230
|
RG_DEFER {
|
|
@@ -4275,6 +4275,26 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
4275
4275
|
}
|
|
4276
4276
|
}
|
|
4277
4277
|
|
|
4278
|
+
// Prepare new environment (if needed)
|
|
4279
|
+
HeapArray<char *> new_env;
|
|
4280
|
+
if (info.reset_env || info.env_variables.len) {
|
|
4281
|
+
if (!info.reset_env) {
|
|
4282
|
+
char **ptr = environ;
|
|
4283
|
+
|
|
4284
|
+
while (*ptr) {
|
|
4285
|
+
new_env.Append(*ptr);
|
|
4286
|
+
ptr++;
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
|
|
4290
|
+
for (const ExecuteInfo::KeyValue &kv: info.env_variables) {
|
|
4291
|
+
const char *var = Fmt(&temp_alloc, "%1=%2", kv.key, kv.value).ptr;
|
|
4292
|
+
new_env.Append((char *)var);
|
|
4293
|
+
}
|
|
4294
|
+
|
|
4295
|
+
new_env.Append(nullptr);
|
|
4296
|
+
}
|
|
4297
|
+
|
|
4278
4298
|
// Start process
|
|
4279
4299
|
pid_t pid;
|
|
4280
4300
|
{
|
|
@@ -4295,12 +4315,12 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
4295
4315
|
return false;
|
|
4296
4316
|
}
|
|
4297
4317
|
|
|
4298
|
-
if (work_dir) {
|
|
4299
|
-
const char *argv[] = {"env", "-C", work_dir, "sh", "-c", cmd_line, nullptr };
|
|
4300
|
-
errno = posix_spawn(&pid, "/bin/env", &file_actions, nullptr, const_cast<char **>(argv), environ);
|
|
4318
|
+
if (info.work_dir) {
|
|
4319
|
+
const char *argv[] = {"env", "-C", info.work_dir, "sh", "-c", cmd_line, nullptr };
|
|
4320
|
+
errno = posix_spawn(&pid, "/bin/env", &file_actions, nullptr, const_cast<char **>(argv), new_env.ptr ? new_env.ptr : environ);
|
|
4301
4321
|
} else {
|
|
4302
4322
|
const char *argv[] = {"sh", "-c", cmd_line, nullptr};
|
|
4303
|
-
errno = posix_spawn(&pid, "/bin/sh", &file_actions, nullptr, const_cast<char **>(argv), environ);
|
|
4323
|
+
errno = posix_spawn(&pid, "/bin/sh", &file_actions, nullptr, const_cast<char **>(argv), new_env.ptr ? new_env.ptr : environ);
|
|
4304
4324
|
}
|
|
4305
4325
|
if (errno) {
|
|
4306
4326
|
LogError("Failed to start process: %1", strerror(errno));
|
|
@@ -4442,7 +4462,7 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
4442
4462
|
|
|
4443
4463
|
#endif
|
|
4444
4464
|
|
|
4445
|
-
bool ExecuteCommandLine(const char *cmd_line, const
|
|
4465
|
+
bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4446
4466
|
Span<const uint8_t> in_buf, Size max_len,
|
|
4447
4467
|
HeapArray<uint8_t> *out_buf, int *out_code)
|
|
4448
4468
|
{
|
|
@@ -4465,8 +4485,8 @@ bool ExecuteCommandLine(const char *cmd_line, const char *work_dir,
|
|
|
4465
4485
|
// Don't f*ck up the log
|
|
4466
4486
|
bool warned = false;
|
|
4467
4487
|
|
|
4468
|
-
bool success = ExecuteCommandLine(cmd_line,
|
|
4469
|
-
|
|
4488
|
+
bool success = ExecuteCommandLine(cmd_line, info, [&]() { return in_buf; },
|
|
4489
|
+
[&](Span<uint8_t> buf) {
|
|
4470
4490
|
if (out_buf->len - start_len <= max_len - buf.len) {
|
|
4471
4491
|
out_buf->Append(buf);
|
|
4472
4492
|
} else if (!warned) {
|
|
@@ -4492,7 +4512,7 @@ Size ReadCommandOutput(const char *cmd_line, Span<char> out_output)
|
|
|
4492
4512
|
};
|
|
4493
4513
|
|
|
4494
4514
|
int exit_code;
|
|
4495
|
-
if (!ExecuteCommandLine(cmd_line,
|
|
4515
|
+
if (!ExecuteCommandLine(cmd_line, {}, MakeSpan((const uint8_t *)nullptr, 0), write, &exit_code))
|
|
4496
4516
|
return -1;
|
|
4497
4517
|
if (exit_code) {
|
|
4498
4518
|
LogDebug("Command '%1 failed (exit code: %2)", cmd_line, exit_code);
|
|
@@ -4505,7 +4525,7 @@ Size ReadCommandOutput(const char *cmd_line, Span<char> out_output)
|
|
|
4505
4525
|
bool ReadCommandOutput(const char *cmd_line, HeapArray<char> *out_output)
|
|
4506
4526
|
{
|
|
4507
4527
|
int exit_code;
|
|
4508
|
-
if (!ExecuteCommandLine(cmd_line,
|
|
4528
|
+
if (!ExecuteCommandLine(cmd_line, {}, {}, Mebibytes(1), out_output, &exit_code))
|
|
4509
4529
|
return false;
|
|
4510
4530
|
if (exit_code) {
|
|
4511
4531
|
LogDebug("Command '%1 failed (exit code: %2)", cmd_line, exit_code);
|
|
@@ -4757,7 +4777,7 @@ bool NotifySystemd()
|
|
|
4757
4777
|
return false;
|
|
4758
4778
|
}
|
|
4759
4779
|
|
|
4760
|
-
|
|
4780
|
+
unsetenv("NOTIFY_SOCKET");
|
|
4761
4781
|
return true;
|
|
4762
4782
|
}
|
|
4763
4783
|
#endif
|
|
@@ -5061,79 +5081,6 @@ const char *CreateUniqueDirectory(Span<const char> directory, const char *prefix
|
|
|
5061
5081
|
// Random
|
|
5062
5082
|
// ------------------------------------------------------------------------
|
|
5063
5083
|
|
|
5064
|
-
static inline uint32_t ROTL32(uint32_t v, int n)
|
|
5065
|
-
{
|
|
5066
|
-
return (v << n) | (v >> (32 - n));
|
|
5067
|
-
}
|
|
5068
|
-
|
|
5069
|
-
static inline uint64_t ROTL64(uint64_t v, int n) {
|
|
5070
|
-
return (v << n) | (v >> (64 - n));
|
|
5071
|
-
}
|
|
5072
|
-
|
|
5073
|
-
FastRandom::FastRandom()
|
|
5074
|
-
{
|
|
5075
|
-
do {
|
|
5076
|
-
FillRandomSafe(state, RG_SIZE(state));
|
|
5077
|
-
} while (std::all_of(std::begin(state), std::end(state), [](uint64_t v) { return !v; }));
|
|
5078
|
-
}
|
|
5079
|
-
|
|
5080
|
-
FastRandom::FastRandom(uint64_t seed)
|
|
5081
|
-
{
|
|
5082
|
-
// splitmix64 generator to seed xoshiro256++, as recommended
|
|
5083
|
-
|
|
5084
|
-
seed += 0x9e3779b97f4a7c15;
|
|
5085
|
-
|
|
5086
|
-
for (int i = 0; i < 4; i++) {
|
|
5087
|
-
seed = (seed ^ (seed >> 30)) * 0xbf58476d1ce4e5b9;
|
|
5088
|
-
seed = (seed ^ (seed >> 27)) * 0x94d049bb133111eb;
|
|
5089
|
-
state[i] = seed ^ (seed >> 31);
|
|
5090
|
-
}
|
|
5091
|
-
}
|
|
5092
|
-
|
|
5093
|
-
void FastRandom::Fill(void *out_buf, Size len)
|
|
5094
|
-
{
|
|
5095
|
-
for (Size i = 0; i < len; i += 8) {
|
|
5096
|
-
uint64_t rnd = Next();
|
|
5097
|
-
|
|
5098
|
-
Size copy_len = std::min(RG_SIZE(rnd), len - i);
|
|
5099
|
-
memcpy((uint8_t *)out_buf + i, &rnd, copy_len);
|
|
5100
|
-
}
|
|
5101
|
-
}
|
|
5102
|
-
|
|
5103
|
-
int FastRandom::GetInt(int min, int max)
|
|
5104
|
-
{
|
|
5105
|
-
int range = max - min;
|
|
5106
|
-
RG_ASSERT(range >= 2);
|
|
5107
|
-
|
|
5108
|
-
unsigned int treshold = (UINT_MAX - UINT_MAX % range);
|
|
5109
|
-
|
|
5110
|
-
unsigned int x;
|
|
5111
|
-
do {
|
|
5112
|
-
Fill(&x, RG_SIZE(x));
|
|
5113
|
-
} while (x >= treshold);
|
|
5114
|
-
x %= range;
|
|
5115
|
-
|
|
5116
|
-
return min + (int)x;
|
|
5117
|
-
}
|
|
5118
|
-
|
|
5119
|
-
uint64_t FastRandom::Next()
|
|
5120
|
-
{
|
|
5121
|
-
// xoshiro256++ by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
|
5122
|
-
// Hopefully I did not screw it up :)
|
|
5123
|
-
|
|
5124
|
-
uint64_t result = ROTL64(state[0] + state[3], 23) + state[0];
|
|
5125
|
-
uint64_t t = state[1] << 17;
|
|
5126
|
-
|
|
5127
|
-
state[2] ^= state[0];
|
|
5128
|
-
state[3] ^= state[1];
|
|
5129
|
-
state[1] ^= state[2];
|
|
5130
|
-
state[0] ^= state[3];
|
|
5131
|
-
state[2] ^= t;
|
|
5132
|
-
state[3] = ROTL64(state[3], 45);
|
|
5133
|
-
|
|
5134
|
-
return result;
|
|
5135
|
-
}
|
|
5136
|
-
|
|
5137
5084
|
static RG_THREAD_LOCAL Size rnd_remain;
|
|
5138
5085
|
static RG_THREAD_LOCAL int64_t rnd_time;
|
|
5139
5086
|
#ifndef _WIN32
|
|
@@ -5143,6 +5090,17 @@ static RG_THREAD_LOCAL uint32_t rnd_state[16];
|
|
|
5143
5090
|
static RG_THREAD_LOCAL uint8_t rnd_buf[64];
|
|
5144
5091
|
static RG_THREAD_LOCAL Size rnd_offset;
|
|
5145
5092
|
|
|
5093
|
+
static thread_local FastRandom rng_fast;
|
|
5094
|
+
|
|
5095
|
+
static inline uint32_t ROTL32(uint32_t v, int n)
|
|
5096
|
+
{
|
|
5097
|
+
return (v << n) | (v >> (32 - n));
|
|
5098
|
+
}
|
|
5099
|
+
|
|
5100
|
+
static inline uint64_t ROTL64(uint64_t v, int n) {
|
|
5101
|
+
return (v << n) | (v >> (64 - n));
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5146
5104
|
static void InitChaCha20(uint32_t state[16], uint32_t key[8], uint32_t iv[2])
|
|
5147
5105
|
{
|
|
5148
5106
|
alignas(uint32_t) static char str[] = "expand 32-byte k";
|
|
@@ -5249,18 +5207,18 @@ void FillRandomSafe(void *out_buf, Size len)
|
|
|
5249
5207
|
|
|
5250
5208
|
memset(rnd_state, 0, RG_SIZE(rnd_state));
|
|
5251
5209
|
#if defined(_WIN32)
|
|
5252
|
-
RG_CRITICAL(RtlGenRandom(&buf, RG_SIZE(buf)), "RtlGenRandom() failed: %
|
|
5210
|
+
RG_CRITICAL(RtlGenRandom(&buf, RG_SIZE(buf)), "RtlGenRandom() failed: %1", GetWin32ErrorString());
|
|
5253
5211
|
#elif defined(__linux__)
|
|
5254
5212
|
{
|
|
5255
5213
|
restart:
|
|
5256
5214
|
int ret = syscall(SYS_getrandom, &buf, RG_SIZE(buf), 0);
|
|
5257
|
-
RG_CRITICAL(ret >= 0, "getentropy() failed: %
|
|
5215
|
+
RG_CRITICAL(ret >= 0, "getentropy() failed: %1", strerror(errno));
|
|
5258
5216
|
|
|
5259
5217
|
if (ret < RG_SIZE(buf))
|
|
5260
5218
|
goto restart;
|
|
5261
5219
|
}
|
|
5262
5220
|
#else
|
|
5263
|
-
RG_CRITICAL(getentropy(&buf, RG_SIZE(buf)) == 0, "getentropy() failed: %
|
|
5221
|
+
RG_CRITICAL(getentropy(&buf, RG_SIZE(buf)) == 0, "getentropy() failed: %1", strerror(errno));
|
|
5264
5222
|
#endif
|
|
5265
5223
|
|
|
5266
5224
|
InitChaCha20(rnd_state, buf.key, buf.iv);
|
|
@@ -5310,6 +5268,75 @@ int GetRandomIntSafe(int min, int max)
|
|
|
5310
5268
|
return min + (int)x;
|
|
5311
5269
|
}
|
|
5312
5270
|
|
|
5271
|
+
FastRandom::FastRandom()
|
|
5272
|
+
{
|
|
5273
|
+
do {
|
|
5274
|
+
FillRandomSafe(state, RG_SIZE(state));
|
|
5275
|
+
} while (std::all_of(std::begin(state), std::end(state), [](uint64_t v) { return !v; }));
|
|
5276
|
+
}
|
|
5277
|
+
|
|
5278
|
+
FastRandom::FastRandom(uint64_t seed)
|
|
5279
|
+
{
|
|
5280
|
+
// splitmix64 generator to seed xoshiro256++, as recommended
|
|
5281
|
+
|
|
5282
|
+
seed += 0x9e3779b97f4a7c15;
|
|
5283
|
+
|
|
5284
|
+
for (int i = 0; i < 4; i++) {
|
|
5285
|
+
seed = (seed ^ (seed >> 30)) * 0xbf58476d1ce4e5b9;
|
|
5286
|
+
seed = (seed ^ (seed >> 27)) * 0x94d049bb133111eb;
|
|
5287
|
+
state[i] = seed ^ (seed >> 31);
|
|
5288
|
+
}
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5291
|
+
void FastRandom::Fill(void *out_buf, Size len)
|
|
5292
|
+
{
|
|
5293
|
+
for (Size i = 0; i < len; i += 8) {
|
|
5294
|
+
uint64_t rnd = Next();
|
|
5295
|
+
|
|
5296
|
+
Size copy_len = std::min(RG_SIZE(rnd), len - i);
|
|
5297
|
+
memcpy((uint8_t *)out_buf + i, &rnd, copy_len);
|
|
5298
|
+
}
|
|
5299
|
+
}
|
|
5300
|
+
|
|
5301
|
+
int FastRandom::GetInt(int min, int max)
|
|
5302
|
+
{
|
|
5303
|
+
int range = max - min;
|
|
5304
|
+
RG_ASSERT(range >= 2);
|
|
5305
|
+
|
|
5306
|
+
unsigned int treshold = (UINT_MAX - UINT_MAX % range);
|
|
5307
|
+
|
|
5308
|
+
unsigned int x;
|
|
5309
|
+
do {
|
|
5310
|
+
x = (unsigned int)Next();
|
|
5311
|
+
} while (x >= treshold);
|
|
5312
|
+
x %= range;
|
|
5313
|
+
|
|
5314
|
+
return min + (int)x;
|
|
5315
|
+
}
|
|
5316
|
+
|
|
5317
|
+
uint64_t FastRandom::Next()
|
|
5318
|
+
{
|
|
5319
|
+
// xoshiro256++ by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
|
5320
|
+
// Hopefully I did not screw it up :)
|
|
5321
|
+
|
|
5322
|
+
uint64_t result = ROTL64(state[0] + state[3], 23) + state[0];
|
|
5323
|
+
uint64_t t = state[1] << 17;
|
|
5324
|
+
|
|
5325
|
+
state[2] ^= state[0];
|
|
5326
|
+
state[3] ^= state[1];
|
|
5327
|
+
state[1] ^= state[2];
|
|
5328
|
+
state[0] ^= state[3];
|
|
5329
|
+
state[2] ^= t;
|
|
5330
|
+
state[3] = ROTL64(state[3], 45);
|
|
5331
|
+
|
|
5332
|
+
return result;
|
|
5333
|
+
}
|
|
5334
|
+
|
|
5335
|
+
int GetRandomIntFast(int min, int max)
|
|
5336
|
+
{
|
|
5337
|
+
return rng_fast.GetInt(min, max);
|
|
5338
|
+
}
|
|
5339
|
+
|
|
5313
5340
|
// ------------------------------------------------------------------------
|
|
5314
5341
|
// Sockets
|
|
5315
5342
|
// ------------------------------------------------------------------------
|
|
@@ -5515,7 +5542,10 @@ struct Task {
|
|
|
5515
5542
|
std::function<bool()> func;
|
|
5516
5543
|
};
|
|
5517
5544
|
|
|
5518
|
-
struct
|
|
5545
|
+
struct WorkerData {
|
|
5546
|
+
AsyncPool *pool = nullptr;
|
|
5547
|
+
int idx;
|
|
5548
|
+
|
|
5519
5549
|
std::mutex queue_mutex;
|
|
5520
5550
|
BucketArray<Task> tasks;
|
|
5521
5551
|
};
|
|
@@ -5531,15 +5561,13 @@ class AsyncPool {
|
|
|
5531
5561
|
int refcount = 0;
|
|
5532
5562
|
|
|
5533
5563
|
int async_count = 0;
|
|
5534
|
-
HeapArray<
|
|
5535
|
-
|
|
5536
|
-
HeapArray<TaskQueue> queues;
|
|
5564
|
+
HeapArray<WorkerData> workers;
|
|
5537
5565
|
std::atomic_int pending_tasks { 0 };
|
|
5538
5566
|
|
|
5539
5567
|
public:
|
|
5540
5568
|
AsyncPool(int threads, bool leak);
|
|
5541
5569
|
|
|
5542
|
-
int GetWorkerCount() const { return (int)
|
|
5570
|
+
int GetWorkerCount() const { return (int)workers.len; }
|
|
5543
5571
|
int CountPendingTasks() const { return pending_tasks; }
|
|
5544
5572
|
|
|
5545
5573
|
void RegisterAsync();
|
|
@@ -5550,7 +5578,7 @@ public:
|
|
|
5550
5578
|
void RunWorker(int worker_idx);
|
|
5551
5579
|
void SyncOn(Async *async);
|
|
5552
5580
|
|
|
5553
|
-
void RunTasks(int
|
|
5581
|
+
void RunTasks(int worker_idx);
|
|
5554
5582
|
void RunTask(Task *task);
|
|
5555
5583
|
};
|
|
5556
5584
|
|
|
@@ -5641,25 +5669,72 @@ AsyncPool::AsyncPool(int threads, bool leak)
|
|
|
5641
5669
|
threads = RG_ASYNC_MAX_THREADS;
|
|
5642
5670
|
}
|
|
5643
5671
|
|
|
5644
|
-
// The first queue is for the main thread
|
|
5645
|
-
|
|
5646
|
-
workers_state.AppendDefault(threads);
|
|
5647
|
-
queues.AppendDefault(threads);
|
|
5672
|
+
// The first queue is for the main thread
|
|
5673
|
+
workers.AppendDefault(threads);
|
|
5648
5674
|
|
|
5649
5675
|
refcount = leak;
|
|
5650
5676
|
}
|
|
5651
5677
|
|
|
5678
|
+
#ifdef _WIN32
|
|
5679
|
+
|
|
5680
|
+
static DWORD WINAPI RunWorkerWin32(void *udata)
|
|
5681
|
+
{
|
|
5682
|
+
WorkerData *worker = (WorkerData *)udata;
|
|
5683
|
+
worker->pool->RunWorker(worker->idx);
|
|
5684
|
+
return 0;
|
|
5685
|
+
}
|
|
5686
|
+
|
|
5687
|
+
#else
|
|
5688
|
+
|
|
5689
|
+
static void *RunWorkerPthread(void *udata)
|
|
5690
|
+
{
|
|
5691
|
+
WorkerData *worker = (WorkerData *)udata;
|
|
5692
|
+
worker->pool->RunWorker(worker->idx);
|
|
5693
|
+
return nullptr;
|
|
5694
|
+
}
|
|
5695
|
+
|
|
5696
|
+
#endif
|
|
5697
|
+
|
|
5652
5698
|
void AsyncPool::RegisterAsync()
|
|
5653
5699
|
{
|
|
5654
5700
|
std::lock_guard<std::mutex> lock_pool(pool_mutex);
|
|
5655
5701
|
|
|
5656
5702
|
if (!async_count++) {
|
|
5657
|
-
for (int i = 1; i <
|
|
5658
|
-
|
|
5659
|
-
|
|
5703
|
+
for (int i = 1; i < workers.len; i++) {
|
|
5704
|
+
WorkerData *worker = &workers[i];
|
|
5705
|
+
|
|
5706
|
+
if (!worker->pool) {
|
|
5707
|
+
worker->pool = this;
|
|
5708
|
+
worker->idx = i;
|
|
5709
|
+
|
|
5710
|
+
#ifdef _WIN32
|
|
5711
|
+
// Our worker threads may exit after main() has returned (or exit has been called),
|
|
5712
|
+
// which can trigger crashes in _Cnd_do_broadcast_at_thread_exit() because it
|
|
5713
|
+
// tries to dereference destroyed stuff. It turns out that std::thread calls this
|
|
5714
|
+
// function, and we don't want that, so avoid std::thread on Windows.
|
|
5715
|
+
HANDLE h = CreateThread(nullptr, 0, RunWorkerWin32, worker, 0, nullptr);
|
|
5716
|
+
if (!h) [[unlikely]] {
|
|
5717
|
+
LogError("Failed to create worker thread: %1", GetWin32ErrorString());
|
|
5718
|
+
|
|
5719
|
+
worker->pool = nullptr;
|
|
5720
|
+
return;
|
|
5721
|
+
}
|
|
5722
|
+
|
|
5723
|
+
CloseHandle(h);
|
|
5724
|
+
#else
|
|
5725
|
+
pthread_t thread;
|
|
5726
|
+
int ret = pthread_create(&thread, nullptr, RunWorkerPthread, worker);
|
|
5727
|
+
if (ret) [[unlikely]] {
|
|
5728
|
+
LogError("Failed to create worker thread: %1", strerror(ret));
|
|
5729
|
+
|
|
5730
|
+
worker->pool = nullptr;
|
|
5731
|
+
return;
|
|
5732
|
+
}
|
|
5733
|
+
|
|
5734
|
+
pthread_detach(thread);
|
|
5735
|
+
#endif
|
|
5660
5736
|
|
|
5661
5737
|
refcount++;
|
|
5662
|
-
workers_state[i] = true;
|
|
5663
5738
|
}
|
|
5664
5739
|
}
|
|
5665
5740
|
}
|
|
@@ -5675,20 +5750,20 @@ void AsyncPool::AddTask(Async *async, const std::function<bool()> &func)
|
|
|
5675
5750
|
{
|
|
5676
5751
|
if (async_running_pool != async->pool) {
|
|
5677
5752
|
for (;;) {
|
|
5678
|
-
int idx =
|
|
5679
|
-
|
|
5753
|
+
int idx = GetRandomIntFast(0, (int)workers.len);
|
|
5754
|
+
WorkerData *worker = &workers[idx];
|
|
5680
5755
|
|
|
5681
|
-
std::unique_lock<std::mutex> lock_queue(
|
|
5756
|
+
std::unique_lock<std::mutex> lock_queue(worker->queue_mutex, std::try_to_lock);
|
|
5682
5757
|
if (lock_queue.owns_lock()) {
|
|
5683
|
-
|
|
5758
|
+
worker->tasks.Append({ async, func });
|
|
5684
5759
|
break;
|
|
5685
5760
|
}
|
|
5686
5761
|
}
|
|
5687
5762
|
} else {
|
|
5688
|
-
|
|
5763
|
+
WorkerData *worker = &workers[async_running_worker_idx];
|
|
5689
5764
|
|
|
5690
|
-
std::lock_guard<std::mutex> lock_queue(
|
|
5691
|
-
|
|
5765
|
+
std::lock_guard<std::mutex> lock_queue(worker->queue_mutex);
|
|
5766
|
+
worker->tasks.Append({ async, func });
|
|
5692
5767
|
}
|
|
5693
5768
|
|
|
5694
5769
|
async->remaining_tasks++;
|
|
@@ -5718,7 +5793,8 @@ void AsyncPool::RunWorker(int worker_idx)
|
|
|
5718
5793
|
pending_cv.wait_for(lock_pool, duration, [&]() { return !!pending_tasks; });
|
|
5719
5794
|
}
|
|
5720
5795
|
|
|
5721
|
-
|
|
5796
|
+
workers[worker_idx].pool = nullptr;
|
|
5797
|
+
|
|
5722
5798
|
if (!--refcount) {
|
|
5723
5799
|
lock_pool.unlock();
|
|
5724
5800
|
delete this;
|
|
@@ -5737,31 +5813,31 @@ void AsyncPool::SyncOn(Async *async)
|
|
|
5737
5813
|
async_running_worker_idx = 0;
|
|
5738
5814
|
|
|
5739
5815
|
while (async->remaining_tasks) {
|
|
5740
|
-
RunTasks(
|
|
5816
|
+
RunTasks(0);
|
|
5741
5817
|
|
|
5742
5818
|
std::unique_lock<std::mutex> lock_sync(pool_mutex);
|
|
5743
5819
|
sync_cv.wait(lock_sync, [&]() { return pending_tasks || !async->remaining_tasks; });
|
|
5744
5820
|
}
|
|
5745
5821
|
}
|
|
5746
5822
|
|
|
5747
|
-
void AsyncPool::RunTasks(int
|
|
5823
|
+
void AsyncPool::RunTasks(int worker_idx)
|
|
5748
5824
|
{
|
|
5749
5825
|
// The '12' factor is pretty arbitrary, don't try to find meaning there
|
|
5750
|
-
for (int i = 0; i <
|
|
5751
|
-
|
|
5752
|
-
std::unique_lock<std::mutex> lock_queue(
|
|
5826
|
+
for (int i = 0; i < workers.len * 12; i++) {
|
|
5827
|
+
WorkerData *worker = &workers[worker_idx];
|
|
5828
|
+
std::unique_lock<std::mutex> lock_queue(worker->queue_mutex, std::try_to_lock);
|
|
5753
5829
|
|
|
5754
|
-
if (lock_queue.owns_lock() &&
|
|
5755
|
-
Task task = std::move(
|
|
5830
|
+
if (lock_queue.owns_lock() && worker->tasks.len) {
|
|
5831
|
+
Task task = std::move(worker->tasks[0]);
|
|
5756
5832
|
|
|
5757
|
-
|
|
5758
|
-
|
|
5833
|
+
worker->tasks.RemoveFirst();
|
|
5834
|
+
worker->tasks.Trim();
|
|
5759
5835
|
|
|
5760
5836
|
lock_queue.unlock();
|
|
5761
5837
|
|
|
5762
5838
|
RunTask(&task);
|
|
5763
5839
|
} else {
|
|
5764
|
-
|
|
5840
|
+
worker_idx = (++worker_idx < workers.len) ? worker_idx : 0;
|
|
5765
5841
|
}
|
|
5766
5842
|
}
|
|
5767
5843
|
}
|
|
@@ -5980,10 +6056,16 @@ void Fiber::FiberCallback(unsigned int high, unsigned int low)
|
|
|
5980
6056
|
static RG_THREAD_LOCAL std::unique_lock<std::mutex> *fib_lock;
|
|
5981
6057
|
static RG_THREAD_LOCAL Fiber *fib_self;
|
|
5982
6058
|
|
|
5983
|
-
Fiber::Fiber(const std::function<bool()> &f, Size
|
|
6059
|
+
Fiber::Fiber(const std::function<bool()> &f, Size)
|
|
5984
6060
|
: f(f)
|
|
5985
6061
|
{
|
|
5986
|
-
|
|
6062
|
+
int ret = pthread_create(&thread, nullptr, ThreadCallback, this);
|
|
6063
|
+
if (ret) {
|
|
6064
|
+
LogError("Failed to create thread: %1", strerror(ret));
|
|
6065
|
+
return;
|
|
6066
|
+
}
|
|
6067
|
+
joinable = true;
|
|
6068
|
+
|
|
5987
6069
|
done = false;
|
|
5988
6070
|
|
|
5989
6071
|
while (toggle == 1) {
|
|
@@ -5996,8 +6078,8 @@ Fiber::~Fiber()
|
|
|
5996
6078
|
// We are forced to execute it until the end
|
|
5997
6079
|
Finalize();
|
|
5998
6080
|
|
|
5999
|
-
if (
|
|
6000
|
-
thread
|
|
6081
|
+
if (joinable) {
|
|
6082
|
+
pthread_join(thread, nullptr);
|
|
6001
6083
|
}
|
|
6002
6084
|
}
|
|
6003
6085
|
|
|
@@ -6028,7 +6110,7 @@ bool Fiber::SwitchBack()
|
|
|
6028
6110
|
}
|
|
6029
6111
|
}
|
|
6030
6112
|
|
|
6031
|
-
void Fiber::ThreadCallback(void *udata)
|
|
6113
|
+
void *Fiber::ThreadCallback(void *udata)
|
|
6032
6114
|
{
|
|
6033
6115
|
Fiber *self = (Fiber *)udata;
|
|
6034
6116
|
|
|
@@ -6045,6 +6127,8 @@ void Fiber::ThreadCallback(void *udata)
|
|
|
6045
6127
|
|
|
6046
6128
|
self->toggle = 0;
|
|
6047
6129
|
self->cv.notify_one();
|
|
6130
|
+
|
|
6131
|
+
return nullptr;
|
|
6048
6132
|
}
|
|
6049
6133
|
|
|
6050
6134
|
void Fiber::Toggle(int to, std::unique_lock<std::mutex> *lock)
|
package/src/core/libcc/libcc.hh
CHANGED
|
@@ -3853,9 +3853,6 @@ Size ConvertWin32WideToUtf8(const wchar_t *str_w, Span<char> out_str);
|
|
|
3853
3853
|
char *GetWin32ErrorString(uint32_t error_code = UINT32_MAX);
|
|
3854
3854
|
#endif
|
|
3855
3855
|
|
|
3856
|
-
void SetEnvironmentVar(const char *name, const char *value);
|
|
3857
|
-
void DeleteEnvironmentVar(const char *name);
|
|
3858
|
-
|
|
3859
3856
|
static inline bool IsPathSeparator(char c)
|
|
3860
3857
|
{
|
|
3861
3858
|
#ifdef _WIN32
|
|
@@ -4055,17 +4052,29 @@ bool CreatePipe(int pfd[2]);
|
|
|
4055
4052
|
void CloseDescriptorSafe(int *fd_ptr);
|
|
4056
4053
|
#endif
|
|
4057
4054
|
|
|
4058
|
-
|
|
4055
|
+
struct ExecuteInfo {
|
|
4056
|
+
struct KeyValue {
|
|
4057
|
+
const char *key;
|
|
4058
|
+
const char *value;
|
|
4059
|
+
};
|
|
4060
|
+
|
|
4061
|
+
const char *work_dir = nullptr;
|
|
4062
|
+
|
|
4063
|
+
bool reset_env = false;
|
|
4064
|
+
Span<const KeyValue> env_variables = {};
|
|
4065
|
+
};
|
|
4066
|
+
|
|
4067
|
+
bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4059
4068
|
FunctionRef<Span<const uint8_t>()> in_func,
|
|
4060
4069
|
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code);
|
|
4061
|
-
bool ExecuteCommandLine(const char *cmd_line, const
|
|
4070
|
+
bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4062
4071
|
Span<const uint8_t> in_buf, Size max_len,
|
|
4063
4072
|
HeapArray<uint8_t> *out_buf, int *out_code);
|
|
4064
4073
|
|
|
4065
4074
|
// Simple variants
|
|
4066
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, const
|
|
4067
|
-
{ return ExecuteCommandLine(cmd_line,
|
|
4068
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, const
|
|
4075
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,int *out_code)
|
|
4076
|
+
{ return ExecuteCommandLine(cmd_line, info, {}, {}, out_code); }
|
|
4077
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4069
4078
|
Span<const uint8_t> in_buf,
|
|
4070
4079
|
FunctionRef<void(Span<uint8_t> buf)> out_func, int *out_code)
|
|
4071
4080
|
{
|
|
@@ -4075,22 +4084,22 @@ static inline bool ExecuteCommandLine(const char *cmd_line, const char *work_dir
|
|
|
4075
4084
|
return buf;
|
|
4076
4085
|
};
|
|
4077
4086
|
|
|
4078
|
-
return ExecuteCommandLine(cmd_line,
|
|
4087
|
+
return ExecuteCommandLine(cmd_line, info, read_once, out_func, out_code);
|
|
4079
4088
|
}
|
|
4080
4089
|
|
|
4081
4090
|
// Char variants
|
|
4082
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, const
|
|
4091
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4083
4092
|
Span<const char> in_buf,
|
|
4084
4093
|
FunctionRef<void(Span<char> buf)> out_func, int *out_code)
|
|
4085
4094
|
{
|
|
4086
4095
|
const auto write = [&](Span<uint8_t> buf) { out_func(buf.As<char>()); };
|
|
4087
|
-
return ExecuteCommandLine(cmd_line,
|
|
4096
|
+
return ExecuteCommandLine(cmd_line, info, in_buf.As<const uint8_t>(), write, out_code);
|
|
4088
4097
|
}
|
|
4089
|
-
static inline bool ExecuteCommandLine(const char *cmd_line, const
|
|
4098
|
+
static inline bool ExecuteCommandLine(const char *cmd_line, const ExecuteInfo &info,
|
|
4090
4099
|
Span<const char> in_buf, Size max_len,
|
|
4091
4100
|
HeapArray<char> *out_buf, int *out_code)
|
|
4092
4101
|
{
|
|
4093
|
-
return ExecuteCommandLine(cmd_line,
|
|
4102
|
+
return ExecuteCommandLine(cmd_line, info, in_buf.As<const uint8_t>(), max_len,
|
|
4094
4103
|
(HeapArray<uint8_t> *)out_buf, out_code);
|
|
4095
4104
|
}
|
|
4096
4105
|
|
|
@@ -4158,6 +4167,11 @@ const char *CreateUniqueDirectory(Span<const char> directory, const char *prefix
|
|
|
4158
4167
|
// Random
|
|
4159
4168
|
// ------------------------------------------------------------------------
|
|
4160
4169
|
|
|
4170
|
+
void ZeroMemorySafe(void *ptr, Size len);
|
|
4171
|
+
void FillRandomSafe(void *buf, Size len);
|
|
4172
|
+
static inline void FillRandomSafe(Span<uint8_t> buf) { FillRandomSafe(buf.ptr, buf.len); }
|
|
4173
|
+
int GetRandomIntSafe(int min, int max);
|
|
4174
|
+
|
|
4161
4175
|
class FastRandom {
|
|
4162
4176
|
uint64_t state[4];
|
|
4163
4177
|
|
|
@@ -4190,10 +4204,7 @@ public:
|
|
|
4190
4204
|
int operator()() { return rng.GetInt(Min, Max); }
|
|
4191
4205
|
};
|
|
4192
4206
|
|
|
4193
|
-
|
|
4194
|
-
void FillRandomSafe(void *buf, Size len);
|
|
4195
|
-
static inline void FillRandomSafe(Span<uint8_t> buf) { FillRandomSafe(buf.ptr, buf.len); }
|
|
4196
|
-
int GetRandomIntSafe(int min, int max);
|
|
4207
|
+
int GetRandomIntFast(int min, int max);
|
|
4197
4208
|
|
|
4198
4209
|
// ------------------------------------------------------------------------
|
|
4199
4210
|
// Sockets
|
|
@@ -4269,7 +4280,8 @@ class Fiber {
|
|
|
4269
4280
|
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4270
4281
|
ucontext_t ucp = {};
|
|
4271
4282
|
#else
|
|
4272
|
-
|
|
4283
|
+
pthread_t thread;
|
|
4284
|
+
bool joinable = false;
|
|
4273
4285
|
|
|
4274
4286
|
std::mutex mutex;
|
|
4275
4287
|
std::condition_variable cv;
|
|
@@ -4297,7 +4309,7 @@ private:
|
|
|
4297
4309
|
#elif defined(RG_FIBER_USE_UCONTEXT)
|
|
4298
4310
|
static void FiberCallback(unsigned int high, unsigned int low);
|
|
4299
4311
|
#else
|
|
4300
|
-
static void ThreadCallback(void *udata);
|
|
4312
|
+
static void *ThreadCallback(void *udata);
|
|
4301
4313
|
void Toggle(int to, std::unique_lock<std::mutex> *lock);
|
|
4302
4314
|
#endif
|
|
4303
4315
|
};
|
package/src/koffi/CMakeLists.txt
CHANGED
|
@@ -31,17 +31,17 @@ find_package(CNoke)
|
|
|
31
31
|
set(CMAKE_CXX_STANDARD 20)
|
|
32
32
|
if(MSVC)
|
|
33
33
|
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
|
|
34
|
-
|
|
35
|
-
add_compile_options(/Zc:__cplusplus /W4 /wd4200 /wd4458 /wd4706 /wd4100 /wd4127 /wd4702 /wd4201 /wd4324)
|
|
34
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus /W4 /wd4200 /wd4201 /wd4127 /wd4458 /wd4706 /wd4702 /wd4324")
|
|
36
35
|
|
|
37
36
|
# ASM_MASM does not (yet) work on Windows ARM64
|
|
38
37
|
if(NOT CMAKE_GENERATOR_PLATFORM MATCHES "ARM64")
|
|
39
38
|
enable_language(ASM_MASM)
|
|
40
39
|
endif()
|
|
41
40
|
else()
|
|
42
|
-
|
|
41
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Wswitch -Werror=switch")
|
|
42
|
+
|
|
43
43
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
44
|
-
|
|
44
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
|
|
45
45
|
endif()
|
|
46
46
|
endif()
|
|
47
47
|
|
|
@@ -132,16 +132,16 @@ if(NOT MSVC OR CMAKE_C_COMPILER_ID MATCHES "[Cc]lang")
|
|
|
132
132
|
# Restore C/C++ compiler sanity
|
|
133
133
|
|
|
134
134
|
if(NOT MSVC)
|
|
135
|
-
target_compile_options(koffi PRIVATE
|
|
136
|
-
|
|
135
|
+
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-strict-aliasing -fwrapv
|
|
136
|
+
-fno-delete-null-pointer-checks>)
|
|
137
137
|
else()
|
|
138
|
-
target_compile_options(koffi PRIVATE
|
|
139
|
-
|
|
138
|
+
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-strict-aliasing /clang:-fwrapv
|
|
139
|
+
-fno-delete-null-pointer-checks>)
|
|
140
140
|
endif()
|
|
141
141
|
|
|
142
142
|
check_cxx_compiler_flag(-fno-finite-loops use_no_finite_loops)
|
|
143
143
|
if(use_no_finite_loops)
|
|
144
|
-
target_compile_options(koffi PRIVATE
|
|
144
|
+
target_compile_options(koffi PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-finite-loops>)
|
|
145
145
|
endif()
|
|
146
146
|
endif()
|
|
147
147
|
enable_unity_build(koffi)
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -2224,7 +2224,7 @@ static Napi::Value ResetKoffi(const Napi::CallbackInfo &info)
|
|
|
2224
2224
|
return env.Undefined();
|
|
2225
2225
|
}
|
|
2226
2226
|
|
|
2227
|
-
static InstanceData *CreateInstance(
|
|
2227
|
+
static InstanceData *CreateInstance()
|
|
2228
2228
|
{
|
|
2229
2229
|
InstanceData *instance = new InstanceData();
|
|
2230
2230
|
RG_DEFER_N(err_guard) { delete instance; };
|
|
@@ -2247,7 +2247,7 @@ static InstanceData *CreateInstance(Napi::Env env)
|
|
|
2247
2247
|
|
|
2248
2248
|
static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
2249
2249
|
{
|
|
2250
|
-
InstanceData *instance = CreateInstance(
|
|
2250
|
+
InstanceData *instance = CreateInstance();
|
|
2251
2251
|
RG_CRITICAL(instance, "Failed to initialize Koffi");
|
|
2252
2252
|
|
|
2253
2253
|
env.SetInstanceData(instance);
|
package/src/koffi/src/win32.cc
CHANGED