Skip to content

Commit 6a10405

Browse files
committed
Spawn Configuration::Concurrency process managers
... and not just one to increase checks/time.
1 parent b06ea2b commit 6a10405

File tree

1 file changed

+66
-37
lines changed

1 file changed

+66
-37
lines changed

lib/base/process.cpp

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "base/process.hpp"
44
#include "base/exception.hpp"
55
#include "base/convert.hpp"
6+
#include "base/configuration.hpp"
67
#include "base/array.hpp"
78
#include "base/objectlock.hpp"
89
#include "base/utility.hpp"
@@ -11,8 +12,10 @@
1112
#include "base/utility.hpp"
1213
#include "base/scriptglobal.hpp"
1314
#include "base/json.hpp"
15+
#include <algorithm>
1416
#include <boost/algorithm/string/join.hpp>
1517
#include <boost/thread/once.hpp>
18+
#include <cstddef>
1619
#include <thread>
1720
#include <iostream>
1821

@@ -32,6 +35,21 @@ extern char **environ;
3235
using namespace icinga;
3336

3437
#define IOTHREADS 4
38+
#define MySpawner l_ProcessControl.Spawners[decltype(l_ProcessControl.Len)(this) / sizeof(void*) % l_ProcessControl.Len]
39+
40+
struct Spawner
41+
{
42+
boost::mutex Mutex;
43+
int FD = -1;
44+
pid_t PID = -1;
45+
46+
void StartSpawnProcessHelper();
47+
void ProcessHandler();
48+
pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment, bool adjustPriority, int fds[3]);
49+
int ProcessKill(pid_t pid, int signum);
50+
int ProcessWaitPID(pid_t pid, int *status);
51+
Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& request);
52+
};
3553

3654
static boost::mutex l_ProcessMutex[IOTHREADS];
3755
static std::map<Process::ProcessHandle, Process::Ptr> l_Processes[IOTHREADS];
@@ -41,9 +59,10 @@ static HANDLE l_Events[IOTHREADS];
4159
static int l_EventFDs[IOTHREADS][2];
4260
static std::map<Process::ConsoleHandle, Process::ProcessHandle> l_FDs[IOTHREADS];
4361

44-
static boost::mutex l_ProcessControlMutex;
45-
static int l_ProcessControlFD = -1;
46-
static pid_t l_ProcessControlPID;
62+
static struct {
63+
Spawner* Spawners = nullptr;
64+
size_t Len = 0;
65+
} l_ProcessControl;
4766
#endif /* _WIN32 */
4867
static boost::once_flag l_ProcessOnceFlag = BOOST_ONCE_INIT;
4968
static boost::once_flag l_SpawnHelperOnceFlag = BOOST_ONCE_INIT;
@@ -68,7 +87,7 @@ Process::~Process()
6887
}
6988

7089
#ifndef _WIN32
71-
static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& request)
90+
Value Spawner::ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& request)
7291
{
7392
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
7493

@@ -138,7 +157,7 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques
138157
if (pid == 0) {
139158
// child process
140159

141-
(void)close(l_ProcessControlFD);
160+
(void)close(FD);
142161

143162
if (setsid() < 0) {
144163
perror("setsid() failed");
@@ -234,7 +253,7 @@ static Value ProcessWaitPIDImpl(struct msghdr *msgh, const Dictionary::Ptr& requ
234253
return response;
235254
}
236255

237-
static void ProcessHandler()
256+
void Spawner::ProcessHandler()
238257
{
239258
sigset_t mask;
240259
sigfillset(&mask);
@@ -248,7 +267,7 @@ static void ProcessHandler()
248267
maxfds = 65536;
249268

250269
for (rlim_t i = 3; i < maxfds; i++)
251-
if (i != static_cast<rlim_t>(l_ProcessControlFD))
270+
if (i != static_cast<rlim_t>(FD))
252271
(void)close(i);
253272
}
254273

@@ -269,7 +288,7 @@ static void ProcessHandler()
269288
msg.msg_control = cbuf;
270289
msg.msg_controllen = sizeof(cbuf);
271290

272-
int rc = recvmsg(l_ProcessControlFD, &msg, 0);
291+
int rc = recvmsg(FD, &msg, 0);
273292

274293
if (rc <= 0) {
275294
if (rc < 0 && (errno == EINTR || errno == EAGAIN))
@@ -282,7 +301,7 @@ static void ProcessHandler()
282301

283302
size_t count = 0;
284303
while (count < length) {
285-
rc = recv(l_ProcessControlFD, mbuf + count, length - count, 0);
304+
rc = recv(FD, mbuf + count, length - count, 0);
286305

287306
if (rc <= 0) {
288307
if (rc < 0 && (errno == EINTR || errno == EAGAIN))
@@ -320,7 +339,7 @@ static void ProcessHandler()
320339

321340
String jresponse = JsonEncode(response);
322341

323-
if (send(l_ProcessControlFD, jresponse.CStr(), jresponse.GetLength(), 0) < 0) {
342+
if (send(FD, jresponse.CStr(), jresponse.GetLength(), 0) < 0) {
324343
BOOST_THROW_EXCEPTION(posix_error()
325344
<< boost::errinfo_api_function("send")
326345
<< boost::errinfo_errno(errno));
@@ -330,13 +349,13 @@ static void ProcessHandler()
330349
_exit(0);
331350
}
332351

333-
static void StartSpawnProcessHelper()
352+
void Spawner::StartSpawnProcessHelper()
334353
{
335-
if (l_ProcessControlFD != -1) {
336-
(void)close(l_ProcessControlFD);
354+
if (FD != -1) {
355+
(void)close(FD);
337356

338357
int status;
339-
(void)waitpid(l_ProcessControlPID, &status, 0);
358+
(void)waitpid(PID, &status, 0);
340359
}
341360

342361
int controlFDs[2];
@@ -357,7 +376,7 @@ static void StartSpawnProcessHelper()
357376
if (pid == 0) {
358377
(void)close(controlFDs[1]);
359378

360-
l_ProcessControlFD = controlFDs[0];
379+
FD = controlFDs[0];
361380

362381
ProcessHandler();
363382

@@ -366,11 +385,11 @@ static void StartSpawnProcessHelper()
366385

367386
(void)close(controlFDs[0]);
368387

369-
l_ProcessControlFD = controlFDs[1];
370-
l_ProcessControlPID = pid;
388+
FD = controlFDs[1];
389+
PID = pid;
371390
}
372391

373-
static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment, bool adjustPriority, int fds[3])
392+
pid_t Spawner::ProcessSpawn(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment, bool adjustPriority, int fds[3])
374393
{
375394
Dictionary::Ptr request = new Dictionary({
376395
{ "command", "spawn" },
@@ -382,7 +401,7 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
382401
String jrequest = JsonEncode(request);
383402
size_t length = jrequest.GetLength();
384403

385-
boost::mutex::scoped_lock lock(l_ProcessControlMutex);
404+
boost::mutex::scoped_lock lock(Mutex);
386405

387406
struct msghdr msg;
388407
memset(&msg, 0, sizeof(msg));
@@ -408,14 +427,14 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
408427
msg.msg_controllen = cmsg->cmsg_len;
409428

410429
do {
411-
while (sendmsg(l_ProcessControlFD, &msg, 0) < 0) {
430+
while (sendmsg(FD, &msg, 0) < 0) {
412431
StartSpawnProcessHelper();
413432
}
414-
} while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
433+
} while (send(FD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
415434

416435
char buf[4096];
417436

418-
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);
437+
ssize_t rc = recv(FD, buf, sizeof(buf), 0);
419438

420439
if (rc <= 0)
421440
return -1;
@@ -430,7 +449,7 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
430449
return response->Get("rc");
431450
}
432451

433-
static int ProcessKill(pid_t pid, int signum)
452+
int Spawner::ProcessKill(pid_t pid, int signum)
434453
{
435454
Dictionary::Ptr request = new Dictionary({
436455
{ "command", "kill" },
@@ -441,17 +460,17 @@ static int ProcessKill(pid_t pid, int signum)
441460
String jrequest = JsonEncode(request);
442461
size_t length = jrequest.GetLength();
443462

444-
boost::mutex::scoped_lock lock(l_ProcessControlMutex);
463+
boost::mutex::scoped_lock lock(Mutex);
445464

446465
do {
447-
while (send(l_ProcessControlFD, &length, sizeof(length), 0) < 0) {
466+
while (send(FD, &length, sizeof(length), 0) < 0) {
448467
StartSpawnProcessHelper();
449468
}
450-
} while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
469+
} while (send(FD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
451470

452471
char buf[4096];
453472

454-
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);
473+
ssize_t rc = recv(FD, buf, sizeof(buf), 0);
455474

456475
if (rc <= 0)
457476
return -1;
@@ -462,7 +481,7 @@ static int ProcessKill(pid_t pid, int signum)
462481
return response->Get("errno");
463482
}
464483

465-
static int ProcessWaitPID(pid_t pid, int *status)
484+
int Spawner::ProcessWaitPID(pid_t pid, int *status)
466485
{
467486
Dictionary::Ptr request = new Dictionary({
468487
{ "command", "waitpid" },
@@ -472,17 +491,17 @@ static int ProcessWaitPID(pid_t pid, int *status)
472491
String jrequest = JsonEncode(request);
473492
size_t length = jrequest.GetLength();
474493

475-
boost::mutex::scoped_lock lock(l_ProcessControlMutex);
494+
boost::mutex::scoped_lock lock(Mutex);
476495

477496
do {
478-
while (send(l_ProcessControlFD, &length, sizeof(length), 0) < 0) {
497+
while (send(FD, &length, sizeof(length), 0) < 0) {
479498
StartSpawnProcessHelper();
480499
}
481-
} while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
500+
} while (send(FD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
482501

483502
char buf[4096];
484503

485-
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);
504+
ssize_t rc = recv(FD, buf, sizeof(buf), 0);
486505

487506
if (rc <= 0)
488507
return -1;
@@ -496,8 +515,18 @@ static int ProcessWaitPID(pid_t pid, int *status)
496515

497516
void Process::InitializeSpawnHelper()
498517
{
499-
if (l_ProcessControlFD == -1)
500-
StartSpawnProcessHelper();
518+
if (!l_ProcessControl.Spawners) {
519+
auto len (std::max(1, Configuration::Concurrency));
520+
521+
l_ProcessControl.Spawners = new Spawner[len];
522+
l_ProcessControl.Len = len;
523+
}
524+
525+
for (Spawner *current = l_ProcessControl.Spawners, *stop = l_ProcessControl.Spawners + l_ProcessControl.Len; current < stop; ++current) {
526+
if (current->FD == -1) {
527+
current->StartSpawnProcessHelper();
528+
}
529+
}
501530
}
502531
#endif /* _WIN32 */
503532

@@ -977,7 +1006,7 @@ void Process::Run(const std::function<void(const ProcessResult&)>& callback)
9771006
fds[1] = outfds[1];
9781007
fds[2] = outfds[1];
9791008

980-
m_Process = ProcessSpawn(m_Arguments, m_ExtraEnvironment, m_AdjustPriority, fds);
1009+
m_Process = MySpawner.ProcessSpawn(m_Arguments, m_ExtraEnvironment, m_AdjustPriority, fds);
9811010
m_PID = m_Process;
9821011

9831012
if (m_PID == -1) {
@@ -1040,7 +1069,7 @@ bool Process::DoEvents()
10401069
#ifdef _WIN32
10411070
TerminateProcess(m_Process, 3);
10421071
#else /* _WIN32 */
1043-
int error = ProcessKill(-m_Process, SIGKILL);
1072+
int error = MySpawner.ProcessKill(-m_Process, SIGKILL);
10441073
if (error) {
10451074
Log(LogWarning, "Process")
10461075
<< "Couldn't kill the process group " << m_PID << " (" << PrettyPrintArguments(m_Arguments)
@@ -1094,7 +1123,7 @@ bool Process::DoEvents()
10941123
int status, exitcode;
10951124
if (could_not_kill || m_PID == -1) {
10961125
exitcode = 128;
1097-
} else if (ProcessWaitPID(m_Process, &status) != m_Process) {
1126+
} else if (MySpawner.ProcessWaitPID(m_Process, &status) != m_Process) {
10981127
exitcode = 128;
10991128

11001129
Log(LogWarning, "Process")

0 commit comments

Comments
 (0)