Skip to content

Commit 895f1d9

Browse files
committed
Spawn Configuration::Concurrency process managers
... and not just one to increase checks/time.
1 parent 0d58029 commit 895f1d9

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+
std::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 std::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 std::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;
@@ -71,7 +90,7 @@ Process::~Process()
7190
}
7291

7392
#ifndef _WIN32
74-
static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& request)
93+
Value Spawner::ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& request)
7594
{
7695
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
7796

@@ -146,7 +165,7 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques
146165
if (pid == 0) {
147166
// child process
148167

149-
(void)close(l_ProcessControlFD);
168+
(void)close(FD);
150169

151170
if (setsid() < 0) {
152171
perror("setsid() failed");
@@ -241,13 +260,13 @@ static Value ProcessWaitPIDImpl(struct msghdr *msgh, const Dictionary::Ptr& requ
241260
return response;
242261
}
243262

244-
static void ProcessHandler()
263+
void Spawner::ProcessHandler()
245264
{
246265
sigset_t mask;
247266
sigfillset(&mask);
248267
sigprocmask(SIG_SETMASK, &mask, nullptr);
249268

250-
Utility::CloseAllFDs({0, 1, 2, l_ProcessControlFD});
269+
Utility::CloseAllFDs({0, 1, 2, FD});
251270

252271
for (;;) {
253272
size_t length;
@@ -266,7 +285,7 @@ static void ProcessHandler()
266285
msg.msg_control = cbuf;
267286
msg.msg_controllen = sizeof(cbuf);
268287

269-
int rc = recvmsg(l_ProcessControlFD, &msg, 0);
288+
int rc = recvmsg(FD, &msg, 0);
270289

271290
if (rc <= 0) {
272291
if (rc < 0 && (errno == EINTR || errno == EAGAIN))
@@ -279,7 +298,7 @@ static void ProcessHandler()
279298

280299
size_t count = 0;
281300
while (count < length) {
282-
rc = recv(l_ProcessControlFD, mbuf + count, length - count, 0);
301+
rc = recv(FD, mbuf + count, length - count, 0);
283302

284303
if (rc <= 0) {
285304
if (rc < 0 && (errno == EINTR || errno == EAGAIN))
@@ -317,7 +336,7 @@ static void ProcessHandler()
317336

318337
String jresponse = JsonEncode(response);
319338

320-
if (send(l_ProcessControlFD, jresponse.CStr(), jresponse.GetLength(), 0) < 0) {
339+
if (send(FD, jresponse.CStr(), jresponse.GetLength(), 0) < 0) {
321340
BOOST_THROW_EXCEPTION(posix_error()
322341
<< boost::errinfo_api_function("send")
323342
<< boost::errinfo_errno(errno));
@@ -327,13 +346,13 @@ static void ProcessHandler()
327346
_exit(0);
328347
}
329348

330-
static void StartSpawnProcessHelper()
349+
void Spawner::StartSpawnProcessHelper()
331350
{
332-
if (l_ProcessControlFD != -1) {
333-
(void)close(l_ProcessControlFD);
351+
if (FD != -1) {
352+
(void)close(FD);
334353

335354
int status;
336-
(void)waitpid(l_ProcessControlPID, &status, 0);
355+
(void)waitpid(PID, &status, 0);
337356
}
338357

339358
int controlFDs[2];
@@ -354,7 +373,7 @@ static void StartSpawnProcessHelper()
354373
if (pid == 0) {
355374
(void)close(controlFDs[1]);
356375

357-
l_ProcessControlFD = controlFDs[0];
376+
FD = controlFDs[0];
358377

359378
ProcessHandler();
360379

@@ -363,11 +382,11 @@ static void StartSpawnProcessHelper()
363382

364383
(void)close(controlFDs[0]);
365384

366-
l_ProcessControlFD = controlFDs[1];
367-
l_ProcessControlPID = pid;
385+
FD = controlFDs[1];
386+
PID = pid;
368387
}
369388

370-
static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment, bool adjustPriority, int fds[3])
389+
pid_t Spawner::ProcessSpawn(const std::vector<String>& arguments, const Dictionary::Ptr& extraEnvironment, bool adjustPriority, int fds[3])
371390
{
372391
Dictionary::Ptr request = new Dictionary({
373392
{ "command", "spawn" },
@@ -379,7 +398,7 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
379398
String jrequest = JsonEncode(request);
380399
size_t length = jrequest.GetLength();
381400

382-
std::unique_lock<std::mutex> lock(l_ProcessControlMutex);
401+
std::unique_lock<std::mutex> lock(Mutex);
383402

384403
struct msghdr msg;
385404
memset(&msg, 0, sizeof(msg));
@@ -405,14 +424,14 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
405424
msg.msg_controllen = cmsg->cmsg_len;
406425

407426
do {
408-
while (sendmsg(l_ProcessControlFD, &msg, 0) < 0) {
427+
while (sendmsg(FD, &msg, 0) < 0) {
409428
StartSpawnProcessHelper();
410429
}
411-
} while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
430+
} while (send(FD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
412431

413432
char buf[4096];
414433

415-
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);
434+
ssize_t rc = recv(FD, buf, sizeof(buf), 0);
416435

417436
if (rc <= 0)
418437
return -1;
@@ -427,7 +446,7 @@ static pid_t ProcessSpawn(const std::vector<String>& arguments, const Dictionary
427446
return response->Get("rc");
428447
}
429448

430-
static int ProcessKill(pid_t pid, int signum)
449+
int Spawner::ProcessKill(pid_t pid, int signum)
431450
{
432451
Dictionary::Ptr request = new Dictionary({
433452
{ "command", "kill" },
@@ -438,17 +457,17 @@ static int ProcessKill(pid_t pid, int signum)
438457
String jrequest = JsonEncode(request);
439458
size_t length = jrequest.GetLength();
440459

441-
std::unique_lock<std::mutex> lock(l_ProcessControlMutex);
460+
std::unique_lock<std::mutex> lock(Mutex);
442461

443462
do {
444-
while (send(l_ProcessControlFD, &length, sizeof(length), 0) < 0) {
463+
while (send(FD, &length, sizeof(length), 0) < 0) {
445464
StartSpawnProcessHelper();
446465
}
447-
} while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
466+
} while (send(FD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
448467

449468
char buf[4096];
450469

451-
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);
470+
ssize_t rc = recv(FD, buf, sizeof(buf), 0);
452471

453472
if (rc <= 0)
454473
return -1;
@@ -459,7 +478,7 @@ static int ProcessKill(pid_t pid, int signum)
459478
return response->Get("errno");
460479
}
461480

462-
static int ProcessWaitPID(pid_t pid, int *status)
481+
int Spawner::ProcessWaitPID(pid_t pid, int *status)
463482
{
464483
Dictionary::Ptr request = new Dictionary({
465484
{ "command", "waitpid" },
@@ -469,17 +488,17 @@ static int ProcessWaitPID(pid_t pid, int *status)
469488
String jrequest = JsonEncode(request);
470489
size_t length = jrequest.GetLength();
471490

472-
std::unique_lock<std::mutex> lock(l_ProcessControlMutex);
491+
std::unique_lock<std::mutex> lock(Mutex);
473492

474493
do {
475-
while (send(l_ProcessControlFD, &length, sizeof(length), 0) < 0) {
494+
while (send(FD, &length, sizeof(length), 0) < 0) {
476495
StartSpawnProcessHelper();
477496
}
478-
} while (send(l_ProcessControlFD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
497+
} while (send(FD, jrequest.CStr(), jrequest.GetLength(), 0) < 0);
479498

480499
char buf[4096];
481500

482-
ssize_t rc = recv(l_ProcessControlFD, buf, sizeof(buf), 0);
501+
ssize_t rc = recv(FD, buf, sizeof(buf), 0);
483502

484503
if (rc <= 0)
485504
return -1;
@@ -493,8 +512,18 @@ static int ProcessWaitPID(pid_t pid, int *status)
493512

494513
void Process::InitializeSpawnHelper()
495514
{
496-
if (l_ProcessControlFD == -1)
497-
StartSpawnProcessHelper();
515+
if (!l_ProcessControl.Spawners) {
516+
auto len (std::max(1, Configuration::Concurrency));
517+
518+
l_ProcessControl.Spawners = new Spawner[len];
519+
l_ProcessControl.Len = len;
520+
}
521+
522+
for (Spawner *current = l_ProcessControl.Spawners, *stop = l_ProcessControl.Spawners + l_ProcessControl.Len; current < stop; ++current) {
523+
if (current->FD == -1) {
524+
current->StartSpawnProcessHelper();
525+
}
526+
}
498527
}
499528
#endif /* _WIN32 */
500529

@@ -980,7 +1009,7 @@ void Process::Run(const std::function<void(const ProcessResult&)>& callback)
9801009
fds[1] = outfds[1];
9811010
fds[2] = outfds[1];
9821011

983-
m_Process = ProcessSpawn(m_Arguments, m_ExtraEnvironment, m_AdjustPriority, fds);
1012+
m_Process = MySpawner.ProcessSpawn(m_Arguments, m_ExtraEnvironment, m_AdjustPriority, fds);
9841013
m_PID = m_Process;
9851014

9861015
if (m_PID == -1) {
@@ -1070,7 +1099,7 @@ bool Process::DoEvents()
10701099
m_OutputStream << "<Timeout exceeded.>";
10711100
TerminateProcess(m_Process, 3);
10721101
#else /* _WIN32 */
1073-
int error = ProcessKill(-m_Process, SIGKILL);
1102+
int error = MySpawner.ProcessKill(-m_Process, SIGKILL);
10741103
if (error) {
10751104
Log(LogWarning, "Process")
10761105
<< "Couldn't kill the process group " << m_PID << " (" << PrettyPrintArguments(m_Arguments)
@@ -1124,7 +1153,7 @@ bool Process::DoEvents()
11241153
int status, exitcode;
11251154
if (could_not_kill || m_PID == -1) {
11261155
exitcode = 128;
1127-
} else if (ProcessWaitPID(m_Process, &status) != m_Process) {
1156+
} else if (MySpawner.ProcessWaitPID(m_Process, &status) != m_Process) {
11281157
exitcode = 128;
11291158

11301159
Log(LogWarning, "Process")

0 commit comments

Comments
 (0)