FEXServer: Adds -w option for waiting on current FEXServer

It can be useful to know in tooling when the current active FEXServer
has exited.

Two things can happen when this command is run.
No FEXServer is active, returns immediately.
A FEXServer is active, we query for a pidfd from the active server, then
we wait until it exits.

Both instances of this is valid to use.
This commit is contained in:
Ryan Houdek committed 2022-06-24 22:56:13 -07:00
1 parent 04a1ac967c
commit e03d253310
6 files changed
+195 -107

No files matched your search

+80 -45
View File
@@ -215,6 +215,72 @@ namespace ProcessPipe {
return true;
}
void SendEmptyErrorPacket(int Socket) {
FEXServerClient::FEXServerResultPacket Res {
.Header {
.Type = FEXServerClient::PacketType::TYPE_ERROR,
},
};
struct iovec iov {
.iov_base = &Res,
.iov_len = sizeof(Res),
};
struct msghdr msg {
.msg_name = nullptr,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
};
sendmsg(Socket, &msg, 0);
}
void SendFDSuccessPacket(int Socket, int FD) {
FEXServerClient::FEXServerResultPacket Res {
.Header {
.Type = FEXServerClient::PacketType::TYPE_SUCCESS,
},
};
struct iovec iov {
.iov_base = &Res,
.iov_len = sizeof(Res),
};
struct msghdr msg {
.msg_name = nullptr,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
};
// Setup the ancillary buffer. This is where we will be getting pipe FDs
// We only need 4 bytes for the FD
constexpr size_t CMSG_SIZE = CMSG_SPACE(sizeof(int));
union AncillaryBuffer {
struct cmsghdr Header;
uint8_t Buffer[CMSG_SIZE];
};
AncillaryBuffer AncBuf{};
// Now link to our ancilllary buffer
msg.msg_control = AncBuf.Buffer;
msg.msg_controllen = CMSG_SIZE;
// Now we need to setup the ancillary buffer data. We are only sending an FD
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
// We are giving the daemon the write side of the pipe
memcpy(CMSG_DATA(cmsg), &FD, sizeof(int));
sendmsg(Socket, &msg, 0);
}
void HandleSocketData(int Socket) {
std::vector<uint8_t> Data(1500);
size_t CurrentRead{};
@@ -266,54 +332,14 @@ namespace ProcessPipe {
CurrentOffset += sizeof(FEXServerClient::FEXServerRequestPacket::BasicRequest);
break;
case FEXServerClient::PacketType::TYPE_GET_LOG_FD: {
FEXServerClient::FEXServerResultPacket Res {
.Header {
.Type = FEXServerClient::PacketType::TYPE_SUCCESS,
},
};
struct iovec iov {
.iov_base = &Res,
.iov_len = sizeof(Res),
};
struct msghdr msg {
.msg_name = nullptr,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
};
if (Logger::LogThreadRunning()) {
// Setup the ancillary buffer. This is where we will be getting pipe FDs
// We only need 4 bytes for the FD
constexpr size_t CMSG_SIZE = CMSG_SPACE(sizeof(int));
union AncillaryBuffer {
struct cmsghdr Header;
uint8_t Buffer[CMSG_SIZE];
};
AncillaryBuffer AncBuf{};
// Now link to our ancilllary buffer
msg.msg_control = AncBuf.Buffer;
msg.msg_controllen = CMSG_SIZE;
// Now we need to setup the ancillary buffer data. We are only sending an FD
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
int fds[2]{};
pipe2(fds, 0);
// 0 = Read
// 1 = Write
Logger::AppendLogFD(fds[0]);
// We are giving the daemon the write side of the pipe
memcpy(CMSG_DATA(cmsg), &fds[1], sizeof(int));
sendmsg(Socket, &msg, 0);
SendFDSuccessPacket(Socket, fds[1]);
// Close the write side now, doesn't matter to us
close(fds[1]);
@@ -324,14 +350,12 @@ namespace ProcessPipe {
}
else {
// Log thread isn't running. Let FEXInterpreter know it can't have one.
Res.Header.Type = FEXServerClient::PacketType::TYPE_ERROR;
sendmsg(Socket, &msg, 0);
SendEmptyErrorPacket(Socket);
}
CurrentOffset += sizeof(FEXServerClient::FEXServerRequestPacket::Header);
break;
}
}
case FEXServerClient::PacketType::TYPE_GET_ROOTFS_PATH: {
std::string MountFolder = SquashFS::GetMountFolder();
@@ -372,6 +396,17 @@ namespace ProcessPipe {
CurrentOffset += sizeof(FEXServerClient::FEXServerRequestPacket::BasicRequest);
break;
}
case FEXServerClient::PacketType::TYPE_GET_PID_FD: {
int FD = ::syscall(SYS_pidfd_open, ::getpid(), 0);
SendFDSuccessPacket(Socket, FD);
// Close the FD now since we've sent it
close(FD);
CurrentOffset += sizeof(FEXServerClient::FEXServerRequestPacket::Header);
break;
}
// Invalid
case FEXServerClient::PacketType::TYPE_ERROR: