mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-28 03:00:53 +01:00
FEXServer: Use a pipe to register new log clients instead of signaling across threads
This commit is contained in:
1 parent
2bb37357c0
commit
e36fb47d98
1 file changed
+56
-59
@@ -12,12 +12,8 @@ void ClientMsgHandler(int FD, FEXServerClient::Logging::PacketMsg* const Msg, co
|
||||
}
|
||||
|
||||
namespace Logger {
|
||||
std::vector<struct pollfd> PollFDs {};
|
||||
std::mutex IncomingPollFDsLock {};
|
||||
std::vector<struct pollfd> IncomingPollFDs {};
|
||||
int LogClientQueuePipe[2];
|
||||
std::thread LogThread;
|
||||
std::atomic<bool> ShouldShutdown {false};
|
||||
std::atomic<int32_t> LoggerThreadTID {};
|
||||
|
||||
void HandleLogData(int Socket) {
|
||||
std::vector<uint8_t> Data(1500);
|
||||
@@ -58,71 +54,75 @@ void HandleLogData(int Socket) {
|
||||
}
|
||||
|
||||
void LogThreadFunc() {
|
||||
LoggerThreadTID = FHU::Syscalls::gettid();
|
||||
std::vector<pollfd> PollFDs;
|
||||
PollFDs.push_back(pollfd {.fd = LogClientQueuePipe[0], .events = POLLIN | POLLHUP, .revents = 0});
|
||||
|
||||
while (!ShouldShutdown) {
|
||||
struct timespec ts {};
|
||||
ts.tv_sec = 5;
|
||||
|
||||
{
|
||||
std::unique_lock lk {IncomingPollFDsLock};
|
||||
PollFDs.insert(PollFDs.end(), std::make_move_iterator(IncomingPollFDs.begin()), std::make_move_iterator(IncomingPollFDs.end()));
|
||||
IncomingPollFDs.clear();
|
||||
while (true) {
|
||||
int Result = ppoll(PollFDs.data(), PollFDs.size(), nullptr, nullptr);
|
||||
if (Result <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (PollFDs.size() == 0) {
|
||||
pselect(0, nullptr, nullptr, nullptr, &ts, nullptr);
|
||||
} else {
|
||||
int Result = ppoll(&PollFDs.at(0), PollFDs.size(), &ts, nullptr);
|
||||
if (Result > 0) {
|
||||
// Walk the FDs and see if we got any results
|
||||
for (auto it = PollFDs.begin(); it != PollFDs.end();) {
|
||||
bool Erase {};
|
||||
if (it->revents != 0) {
|
||||
if (it->revents & POLLIN) {
|
||||
// Data from the socket
|
||||
HandleLogData(it->fd);
|
||||
} else if (it->revents & (POLLHUP | POLLERR | POLLNVAL | POLLRDHUP)) {
|
||||
// Error or hangup, close the socket and erase it from our list
|
||||
Erase = true;
|
||||
close(it->fd);
|
||||
}
|
||||
|
||||
it->revents = 0;
|
||||
--Result;
|
||||
}
|
||||
// Process events for client pipe
|
||||
if (PollFDs[0].revents) {
|
||||
--Result;
|
||||
|
||||
if (Erase) {
|
||||
it = PollFDs.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
auto [PipeFD, _, revents] = PollFDs[0];
|
||||
PollFDs[0].revents = 0;
|
||||
|
||||
if (Result == 0) {
|
||||
// Early break if we've consumed all the results
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (revents & POLLIN) {
|
||||
int ReceivedFD;
|
||||
read(PipeFD, &ReceivedFD, sizeof(ReceivedFD));
|
||||
PollFDs.push_back(pollfd {
|
||||
.fd = ReceivedFD,
|
||||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
});
|
||||
}
|
||||
|
||||
if (revents & POLLHUP) {
|
||||
close(PipeFD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Process events for log FDs
|
||||
for (auto it = PollFDs.begin() + 1; Result && it != PollFDs.end();) {
|
||||
if (it->revents == 0) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
--Result;
|
||||
|
||||
bool Erase {};
|
||||
if (it->revents & POLLIN) {
|
||||
// Data from the socket
|
||||
HandleLogData(it->fd);
|
||||
} else if (it->revents & (POLLHUP | POLLERR | POLLNVAL | POLLRDHUP)) {
|
||||
// Error or hangup, close the socket and erase it from our list
|
||||
Erase = true;
|
||||
close(it->fd);
|
||||
}
|
||||
|
||||
it->revents = 0;
|
||||
|
||||
if (Erase) {
|
||||
it = PollFDs.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartLogThread() {
|
||||
pipe2(LogClientQueuePipe, 0);
|
||||
|
||||
LogThread = std::thread(LogThreadFunc);
|
||||
}
|
||||
|
||||
void AppendLogFD(int FD) {
|
||||
{
|
||||
std::unique_lock lk {IncomingPollFDsLock};
|
||||
IncomingPollFDs.emplace_back(pollfd {
|
||||
.fd = FD,
|
||||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
});
|
||||
}
|
||||
|
||||
// Wake up the thread immediately
|
||||
FHU::Syscalls::tgkill(::getpid(), LoggerThreadTID, SIGUSR1);
|
||||
write(LogClientQueuePipe[1], &FD, sizeof(FD));
|
||||
}
|
||||
|
||||
bool LogThreadRunning() {
|
||||
@@ -130,10 +130,7 @@ bool LogThreadRunning() {
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
ShouldShutdown = true;
|
||||
|
||||
// Wake up the thread immediately
|
||||
FHU::Syscalls::tgkill(::getpid(), LoggerThreadTID, SIGUSR1);
|
||||
close(LogClientQueuePipe[1]);
|
||||
|
||||
if (LogThread.joinable()) {
|
||||
LogThread.join();
|
||||
|
||||
Reference in new issue
Block a user