Skip to content

Commit be84169

Browse files
Fix logging segfault by leaking logger
There is a race between activity and logger teardown, so we switch from a unique_ptr to a raw pointer and leak the logger so it persists across all activity teardowns. Signed-off-by: Lisanna Dettwyler <lisanna.dettwyler@gmail.com>
1 parent bc385bc commit be84169

9 files changed

Lines changed: 22 additions & 22 deletions

File tree

src/libexpr-tests/primops.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ class CaptureLogger : public Logger
3232

3333
class CaptureLogging
3434
{
35-
std::unique_ptr<Logger> oldLogger;
35+
Logger * oldLogger;
3636
public:
3737
CaptureLogging()
3838
{
39-
oldLogger = std::move(logger);
40-
logger = std::make_unique<CaptureLogger>();
39+
oldLogger = logger;
40+
logger = new CaptureLogger();
4141
}
4242

4343
~CaptureLogging()
4444
{
45-
logger = std::move(oldLogger);
45+
logger = oldLogger;
4646
}
4747
};
4848

@@ -144,7 +144,7 @@ TEST_F(PrimOpTest, trace)
144144
CaptureLogging l;
145145
auto v = eval("builtins.trace \"test string 123\" 123");
146146
ASSERT_THAT(v, IsIntEq(123));
147-
auto text = (dynamic_cast<CaptureLogger *>(logger.get()))->get();
147+
auto text = (dynamic_cast<CaptureLogger *>(logger))->get();
148148
ASSERT_NE(text.find("test string 123"), std::string::npos);
149149
}
150150

src/libmain/loggers.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void setLogFormat(const std::string & logFormatStr)
5050
void setLogFormat(const LogFormat & logFormat)
5151
{
5252
defaultLogFormat = logFormat;
53-
logger = makeDefaultLogger();
53+
logger = makeDefaultLogger().release();
5454
}
5555

5656
} // namespace nix

src/libstore/daemon.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,14 +1047,11 @@ void processConnection(ref<Store> store, FdSource && from, FdSink && to, Trusted
10471047
conn.to = std::move(to);
10481048
conn.from = std::move(from);
10491049

1050-
auto tunnelLogger_ = std::make_unique<TunnelLogger>(conn.to, conn.protoVersion);
1051-
auto tunnelLogger = tunnelLogger_.get();
1052-
std::unique_ptr<Logger> prevLogger_;
1053-
auto prevLogger = logger.get();
1050+
auto tunnelLogger = new TunnelLogger(conn.to, conn.protoVersion);
1051+
auto prevLogger = logger;
10541052
// FIXME
10551053
if (!recursive) {
1056-
prevLogger_ = std::move(logger);
1057-
logger = std::move(tunnelLogger_);
1054+
logger = tunnelLogger;
10581055
applyJSONLogger();
10591056
}
10601057

src/libstore/unix/build/child.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace nix {
99

1010
void commonChildInit()
1111
{
12-
logger = makeSimpleLogger();
12+
logger = makeSimpleLogger().release();
1313

1414
const static std::string pathNullDevice = "/dev/null";
1515
restoreProcessContext(false);

src/libstore/unix/build/derivation-builder.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ void DerivationBuilderImpl::runChild(RunChildArgs args)
13761376
/* If this is a builtin builder, call it now. This should not return. */
13771377
if (drv.isBuiltin()) {
13781378
try {
1379-
logger = makeJSONLogger(getStandardError());
1379+
logger = makeJSONLogger(getStandardError()).release();
13801380

13811381
for (auto & e : drv.outputs)
13821382
ctx.outputs.insert_or_assign(e.first, store.printStorePath(scratchOutputs.at(e.first)));

src/libutil/include/nix/util/logging.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ struct PushActivity
255255
}
256256
};
257257

258-
extern std::unique_ptr<Logger> logger;
258+
extern Logger * logger;
259259

260260
std::unique_ptr<Logger> makeSimpleLogger(bool printBuildLogs = true);
261261

src/libutil/logging.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ void setCurActivity(const ActivityId activityId)
3030
curActivity = activityId;
3131
}
3232

33-
std::unique_ptr<Logger> logger = makeSimpleLogger(true);
33+
/**
34+
* This is a raw pointer to allow it to leak.
35+
* Avoids races in activity teardown.
36+
*/
37+
Logger * logger = makeSimpleLogger(true).release();
3438

3539
void Logger::warn(const std::string & msg)
3640
{
@@ -381,7 +385,7 @@ void applyJSONLogger()
381385
std::vector<std::unique_ptr<Logger>> loggers;
382386
loggers.push_back(makeJSONLogger(*opt, false));
383387
try {
384-
logger = makeTeeLogger(std::move(logger), std::move(loggers));
388+
logger = makeTeeLogger(std::unique_ptr<Logger>(logger), std::move(loggers)).release();
385389
} catch (...) {
386390
// `logger` is now gone so give up.
387391
abort();

src/libutil/unix/processes.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,16 +233,15 @@ static int childEntry(void * arg)
233233

234234
pid_t startProcess(fun<void()> processMain, const ProcessOptions & options)
235235
{
236-
auto newLogger = makeSimpleLogger();
236+
auto newLogger = makeSimpleLogger().release();
237237
ChildWrapperFunction wrapper = [&] {
238238
if (!options.allowVfork) {
239-
/* Set a simple logger, while releasing (not destroying)
239+
/* Set a simple logger, while leaking (not destroying)
240240
the parent logger. We don't want to run the parent
241241
logger's destructor since that will crash (e.g. when
242242
~ProgressBar() tries to join a thread that doesn't
243243
exist. */
244-
logger.release();
245-
logger = std::move(newLogger);
244+
logger = newLogger;
246245
}
247246
try {
248247
#ifdef __linux__

src/nix/build-remote/build-remote.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static int main_build_remote(int argc, char ** argv)
7070
if (pthread_sigmask(SIG_UNBLOCK, &set, nullptr))
7171
throw SysError("unblocking SIGTERM");
7272

73-
logger = makeJSONLogger(getStandardError());
73+
logger = makeJSONLogger(getStandardError()).release();
7474

7575
/* Ensure we don't get any SSH passphrase or host key popups. */
7676
unsetenv("DISPLAY");

0 commit comments

Comments
 (0)