From abb7b710044a2ac8c1b3d3266585f5e183d02c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 10 Jul 2015 17:05:17 +0200 Subject: [PATCH] launch_daemon: Fixed a race condition in Worker startup. * When the thread is started during the construction of the base class, the virtual method table may still point to the methods of the base class when the thread actually starts to run. * This caused the main worker to have a timeout, which could eventually be reached which in turn caused all job processing to stop. * That's what you get when you do Java all day; whoever designed C++ should be slapped (I'm talking to you, Bjarne). --- src/servers/launch/LaunchDaemon.cpp | 2 ++ src/servers/launch/Worker.cpp | 27 +++++++++++++++++++++------ src/servers/launch/Worker.h | 2 ++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 9d56171b59..63a6245aae 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -164,6 +164,8 @@ LaunchDaemon::LaunchDaemon(bool userMode, status_t& error) fUserMode(userMode) { fMainWorker = new MainWorker(fJobQueue); + fMainWorker->Init(); + if (fInitTarget != NULL) _AddTarget(fInitTarget); diff --git a/src/servers/launch/Worker.cpp b/src/servers/launch/Worker.cpp index d435a179a9..5e337603b4 100644 --- a/src/servers/launch/Worker.cpp +++ b/src/servers/launch/Worker.cpp @@ -15,12 +15,9 @@ static int32 sWorkerCount; Worker::Worker(JobQueue& queue) : + fThread(-1), fJobQueue(queue) { - fThread = spawn_thread(&Worker::_Process, "worker", B_NORMAL_PRIORITY, - this); - if (fThread >= 0 && resume_thread(fThread) == B_OK) - atomic_add(&sWorkerCount, 1); } @@ -29,6 +26,22 @@ Worker::~Worker() } +status_t +Worker::Init() +{ + fThread = spawn_thread(&Worker::_Process, "worker", B_NORMAL_PRIORITY, + this); + if (fThread < 0) + return fThread; + + status_t status = resume_thread(fThread); + if (status == B_OK) + atomic_add(&sWorkerCount, 1); + + return status; +} + + status_t Worker::Process() { @@ -103,8 +116,10 @@ MainWorker::Run(BJob* job) if (jobCount > INT_MAX) jobCount = INT_MAX; - if ((int32)jobCount > count && count < fCPUCount) - new Worker(fJobQueue); + if ((int32)jobCount > count && count < fCPUCount) { + Worker* worker = new Worker(fJobQueue); + worker->Init(); + } return Worker::Run(job); } diff --git a/src/servers/launch/Worker.h b/src/servers/launch/Worker.h index bcc3e28aa4..beb333d1f3 100644 --- a/src/servers/launch/Worker.h +++ b/src/servers/launch/Worker.h @@ -19,6 +19,8 @@ public: Worker(JobQueue& queue); virtual ~Worker(); + status_t Init(); + protected: virtual status_t Process(); virtual bigtime_t Timeout() const;