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

Implement setStackSize on Windows #10737

Merged
merged 5 commits into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions src/libutil/current-process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ unsigned int getMaxCPU()
//////////////////////////////////////////////////////////////////////


#ifndef _WIN32
rlim_t savedStackSize = 0;
size_t savedStackSize = 0;

void setStackSize(rlim_t stackSize)
void setStackSize(size_t stackSize)
{
#ifndef _WIN32
struct rlimit limit;
if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) {
savedStackSize = limit.rlim_cur;
limit.rlim_cur = std::min(stackSize, limit.rlim_max);
limit.rlim_cur = std::min(static_cast<rlim_t>(stackSize), limit.rlim_max);
if (setrlimit(RLIMIT_STACK, &limit) != 0) {
logger->log(
lvlError,
Expand All @@ -81,8 +81,31 @@ void setStackSize(rlim_t stackSize)
);
}
}
#else
ULONG_PTR stackLow, stackHigh;
GetCurrentThreadStackLimits(&stackLow, &stackHigh);
ULONG maxStackSize = stackHigh - stackLow;
ULONG currStackSize = 0;
// This retrieves the current promised stack size
SetThreadStackGuarantee(&currStackSize);
if (currStackSize < stackSize) {
savedStackSize = currStackSize;
ULONG newStackSize = std::min(static_cast<ULONG>(stackSize), maxStackSize);
if (SetThreadStackGuarantee(&newStackSize) == 0) {
logger->log(
lvlError,
HintFmt(
"Failed to increase stack size from %1% to %2% (maximum allowed stack size: %3%): %4%",
savedStackSize,
stackSize,
maxStackSize,
std::to_string(GetLastError())
).str()
);
}
}
#endif
}
#endif

void restoreProcessContext(bool restoreMounts)
{
Expand Down
4 changes: 1 addition & 3 deletions src/libutil/current-process.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ namespace nix {
*/
unsigned int getMaxCPU();

#ifndef _WIN32 // TODO implement on Windows, if needed.
/**
* Change the stack size.
*/
void setStackSize(rlim_t stackSize);
#endif
void setStackSize(size_t stackSize);

/**
* Restore the original inherited Unix process context (such as signal
Expand Down
5 changes: 5 additions & 0 deletions src/nix/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ nix_LIBS = libexpr libmain libfetchers libstore libutil libcmd

nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS)

ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
nix_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif

$(foreach name, \
nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \
$(eval $(call install-symlink, nix, $(bindir)/$(name))))
Expand Down
2 changes: 0 additions & 2 deletions src/nix/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -522,11 +522,9 @@ void mainWrapped(int argc, char * * argv)

int main(int argc, char * * argv)
{
#ifndef _WIN32 // TODO implement on Windows
// Increase the default stack size for the evaluator and for
// libstdc++'s std::regex.
nix::setStackSize(64 * 1024 * 1024);
#endif

return nix::handleExceptions(argv[0], [&]() {
nix::mainWrapped(argc, argv);
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/libexpr/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ libexpr-tests_LIBS = \
libexpr libexprc libfetchers libstore libstorec libutil libutilc

libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock

ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif
5 changes: 5 additions & 0 deletions tests/unit/libfetchers/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ libfetchers-tests_LIBS = \
libfetchers libstore libutil

libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif
5 changes: 5 additions & 0 deletions tests/unit/libstore/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ libstore-tests_LIBS = \
libstore libstorec libutil libutilc

libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif
5 changes: 5 additions & 0 deletions tests/unit/libutil/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ libutil-tests_LIBS = libutil-test-support libutil libutilc

libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif

check: $(d)/data/git/check-data.sh.test

$(eval $(call run-test,$(d)/data/git/check-data.sh))
Loading