35 m_transceiver(std::bind(
38 std::placeholders::_1,
39 std::placeholders::_2)),
46 m_managementRecordCount(0),
47 m_badSocketMessageCount(0),
48 m_badSocketKillCount(0),
50 m_activeThreads(threads),
55 FAIL_LOG(
"You're not allowed to have multiple manager instances")
57 DIAG_LOG(
"Manager_base::Manager_base(): Initialized")
62 std::lock_guard<std::mutex> lock(m_tasksMutex);
64 m_transceiver.terminate();
70 std::lock_guard<std::mutex> lock(m_tasksMutex);
78 std::lock_guard<std::mutex> lock(m_tasksMutex);
79 DIAG_LOG(
"Starting fastcgi++ manager")
82 m_transceiver.start();
83 for(
auto& thread: m_threads)
84 if(!thread.joinable())
87 thread.swap(newThread);
93 for(
auto& thread: m_threads)
102 struct sigaction sigAction;
104 sigemptyset(&sigAction.sa_mask);
105 sigAction.sa_flags=0;
107 sigaction(SIGPIPE, &sigAction, NULL);
108 sigaction(SIGUSR1, &sigAction, NULL);
109 sigaction(SIGTERM, &sigAction, NULL);
120 DIAG_LOG(
"Received SIGUSR1. Stopping fastcgi++ manager.")
124 WARNING_LOG(
"Received SIGUSR1 but fastcgi++ manager isn't "\
132 DIAG_LOG(
"Received SIGTERM. Terminating fastcgi++ manager.")
133 instance->terminate();
136 WARNING_LOG(
"Received SIGTERM but fastcgi++ manager isn't "\
148 std::lock_guard<std::mutex> lock(m_messagesMutex);
149 message = std::move(m_messages.front().first);
150 socket = m_messages.front().second;
154 if(message.
type == 0)
177 if(std::equal(name, value,
"FCGI_MAX_CONNS"))
180 reinterpret_cast<const char*
>(
192 if(std::equal(name, value,
"FCGI_MAX_REQS"))
195 reinterpret_cast<const char*
>(
207 if(std::equal(name, value,
"FCGI_MPXS_CONNS"))
210 reinterpret_cast<const char*
>(
244 m_transceiver.send(socket, std::move(record),
false);
251 ERROR_LOG(
"Got a non-FastCGI record destined for the manager")
256 std::unique_lock<std::shared_timed_mutex> requestsWriteLock(
259 std::unique_lock<std::mutex> tasksLock(m_tasksMutex);
260 std::shared_lock<std::shared_timed_mutex> requestsReadLock(m_requestsMutex);
262 while(!m_terminate && !(m_stop && m_requests.empty()))
264 requestsReadLock.unlock();
265 while(!m_tasks.empty())
267 auto id = m_tasks.front();
275 requestsReadLock.lock();
276 auto request = m_requests.find(
id);
277 if(request != m_requests.end())
279 std::unique_lock<std::mutex> requestLock(
280 request->second->mutex,
282 requestsReadLock.unlock();
286 auto lock = request->second->handler();
287 if(!lock || !
id.m_socket.valid())
289 #if FASTCGIPP_LOG_LEVEL > 3
290 if(!
id.m_socket.valid())
291 ++m_badSocketKillCount;
295 requestsWriteLock.lock();
296 requestLock.unlock();
297 m_requests.erase(request);
298 requestsWriteLock.unlock();
302 requestLock.unlock();
308 requestsReadLock.unlock();
313 requestsReadLock.lock();
314 if(m_terminate || (m_stop && m_requests.empty()))
316 requestsReadLock.unlock();
317 #if FASTCGIPP_LOG_LEVEL > 3
320 m_wake.wait(tasksLock);
321 #if FASTCGIPP_LOG_LEVEL > 3
322 if(!m_stop && !m_terminate)
325 m_maxActiveThreads = std::max(m_activeThreads, m_maxActiveThreads);
328 requestsReadLock.lock();
336 #if FASTCGIPP_LOG_LEVEL > 3
337 ++m_managementRecordCount;
339 std::lock_guard<std::mutex> lock(m_messagesMutex);
340 m_messages.push(std::make_pair(std::move(message),
id.m_socket));
344 #if FASTCGIPP_LOG_LEVEL > 3
345 ++m_badSocketMessageCount;
347 std::lock_guard<std::shared_timed_mutex> lock(m_requestsMutex);
348 const auto range = m_requests.equal_range(
id.m_socket);
349 auto request = range.first;
350 while(request != range.second)
352 std::unique_lock<std::mutex> lock(
353 request->second->mutex,
358 request = m_requests.erase(request);
359 #if FASTCGIPP_LOG_LEVEL > 3
360 ++m_badSocketKillCount;
370 #if FASTCGIPP_LOG_LEVEL > 3
373 std::unique_lock<std::shared_timed_mutex> lock(m_requestsMutex);
374 auto request = m_requests.find(
id);
375 if(request == m_requests.end())
377 if(message.type == 0)
388 request = m_requests.emplace(
389 std::piecewise_construct,
390 std::forward_as_tuple(
id),
391 std::forward_as_tuple()).first;
393 request->second = makeRequest(
398 #if FASTCGIPP_LOG_LEVEL > 3
400 m_maxRequests = std::max(m_maxRequests, m_requests.size());
404 WARNING_LOG(
"Got a non BEGIN_REQUEST record for a request"\
405 " that doesn't exist")
410 request->second->push(std::move(message));
412 std::lock_guard<std::mutex> lock(m_tasksMutex);
421 m_threads.resize(threads);
422 #if FASTCGIPP_LOG_LEVEL > 3
423 m_activeThreads = threads;
432 DIAG_LOG(
"Manager_base::~Manager_base(): New requests ============== " \
434 DIAG_LOG(
"Manager_base::~Manager_base(): Max concurrent requests === " \
436 DIAG_LOG(
"Manager_base::~Manager_base(): Management records ======== " \
437 << m_managementRecordCount)
438 DIAG_LOG(
"Manager_base::~Manager_base(): Bad socket messages ======= " \
439 << m_badSocketMessageCount)
440 DIAG_LOG(
"Manager_base::~Manager_base(): Bad socket request kills == " \
441 << m_badSocketKillCount)
442 DIAG_LOG(
"Manager_base::~Manager_base(): Request messages received = " \
444 DIAG_LOG(
"Manager_base::~Manager_base(): Maximum active threads ==== " \
445 << m_maxActiveThreads)
446 DIAG_LOG(
"Manager_base::~Manager_base(): Remaining requests ======== " \
447 << m_requests.size())
448 DIAG_LOG(
"Manager_base::~Manager_base(): Remaining tasks =========== " \
450 DIAG_LOG(
"Manager_base::~Manager_base(): Remaining local messages == " \
451 << m_messages.size())