fix(libSceNet): sceNetEpollWait takes 2 as the OUT event
sceNetEpollWait used Linux's EPOLLOUT bit (4) for writability. The SCE value is 2 (shadPS4 net_types.h ORBIS_NET_EPOLLOUT, KytyPS5 network.cpp EPOLL_OUT, SharpProspero Socket.cs EpollOut); IN (1), ERR (8) and HUP (0x10) already match. A socket registered for OUT was never polled for writability, so the wait ran out its timeout or blocked forever, and an IN|OUT registration never reported OUT.
This commit is contained in:
parent
2a5eca11cd
commit
b19a74f5bf
|
|
@ -1071,14 +1071,14 @@ int APS5_VABI sceNetEpollWait(int eid, NetEpollEvent* events, int maxevents, int
|
|||
for (std::size_t index = 0; index < descriptors.size(); ++index) {
|
||||
descriptors[index].fd = native_sockets[index]->value;
|
||||
if (registered_events[index].events & 1) descriptors[index].events |= POLLRDNORM;
|
||||
if (registered_events[index].events & 4) descriptors[index].events |= POLLWRNORM;
|
||||
if (registered_events[index].events & 2) descriptors[index].events |= POLLWRNORM;
|
||||
}
|
||||
#else
|
||||
std::vector<pollfd> descriptors(registered_events.size());
|
||||
for (std::size_t index = 0; index < descriptors.size(); ++index) {
|
||||
descriptors[index].fd = native_sockets[index]->value;
|
||||
if (registered_events[index].events & 1) descriptors[index].events |= POLLIN;
|
||||
if (registered_events[index].events & 4) descriptors[index].events |= POLLOUT;
|
||||
if (registered_events[index].events & 2) descriptors[index].events |= POLLOUT;
|
||||
}
|
||||
#endif
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
|
|
@ -1108,10 +1108,10 @@ int APS5_VABI sceNetEpollWait(int eid, NetEpollEvent* events, int maxevents, int
|
|||
std::uint32_t guest_events = 0;
|
||||
#ifdef _WIN32
|
||||
if (native_events & (POLLRDNORM | POLLPRI)) guest_events |= 1;
|
||||
if (native_events & POLLWRNORM) guest_events |= 4;
|
||||
if (native_events & POLLWRNORM) guest_events |= 2;
|
||||
#else
|
||||
if (native_events & (POLLIN | POLLPRI)) guest_events |= 1;
|
||||
if (native_events & POLLOUT) guest_events |= 4;
|
||||
if (native_events & POLLOUT) guest_events |= 2;
|
||||
#endif
|
||||
if (native_events & POLLERR) guest_events |= 8;
|
||||
if (native_events & POLLHUP) guest_events |= 16;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,38 @@ static void CheckEmptyEpoll() {
|
|||
}
|
||||
}
|
||||
|
||||
static void CheckEpollWritable() {
|
||||
std::array<std::uint8_t, 16> address{16, 2, 0, 0, 127, 0, 0, 1};
|
||||
const int receiver = sceNetSocket("epoll-receiver", 2, 2, 17);
|
||||
const int sender = sceNetSocket("epoll-sender", 2, 2, 17);
|
||||
Require(receiver >= 0 && sender >= 0);
|
||||
Require(sceNetBind_nid_postfix(receiver, address.data(), address.size()) == 0);
|
||||
std::uint32_t size = address.size();
|
||||
Require(sceNetGetsockname(receiver, address.data(), &size) == 0 && size == address.size());
|
||||
const int epoll = sceNetEpollCreate("epoll-writable", 0);
|
||||
Require(epoll >= 0);
|
||||
NetEpollEvent registration{};
|
||||
registration.events = 2;
|
||||
registration.ident = static_cast<std::uint64_t>(sender);
|
||||
registration.data.u32 = 41;
|
||||
Require(sceNetEpollControl(epoll, 1, sender, ®istration) == 0);
|
||||
NetEpollEvent ready{};
|
||||
Require(sceNetEpollWait(epoll, &ready, 1, 1000000) == 1);
|
||||
Require(ready.events == 2 && ready.ident == static_cast<std::uint64_t>(sender) && ready.data.u32 == 41);
|
||||
Require(sceNetEpollControl(epoll, 3, sender, nullptr) == 0);
|
||||
const char payload[] = "epoll";
|
||||
char peeked[sizeof(payload)]{};
|
||||
Require(sceNetSendto(sender, payload, sizeof(payload), 0, address.data(), address.size()) == sizeof(payload));
|
||||
Require(sceNetRecv(receiver, peeked, sizeof(peeked), 2) == sizeof(payload));
|
||||
registration.events = 3;
|
||||
registration.ident = static_cast<std::uint64_t>(receiver);
|
||||
Require(sceNetEpollControl(epoll, 1, receiver, ®istration) == 0);
|
||||
Require(sceNetEpollWait(epoll, &ready, 1, 1000000) == 1);
|
||||
Require(ready.events == 3 && ready.ident == static_cast<std::uint64_t>(receiver) && ready.data.u32 == 41);
|
||||
Require(sceNetEpollDestroy(epoll) == 0);
|
||||
Require(sceNetSocketClose(sender) == 0 && sceNetSocketClose(receiver) == 0);
|
||||
}
|
||||
|
||||
static void CheckReceiveTimeout(int receiver, int sender, const std::array<std::uint8_t, 16>& address) {
|
||||
const int timeout = 50000;
|
||||
Require(sceNetSetsockopt(receiver, 0xffff, 0x1006, &timeout, sizeof(timeout)) == 0);
|
||||
|
|
@ -353,6 +385,7 @@ int main() {
|
|||
Require(sceNetInit_nid_postfix() == 0);
|
||||
CheckPoolStats();
|
||||
CheckEmptyEpoll();
|
||||
CheckEpollWritable();
|
||||
CheckAddressText(2, "127.0.0.1");
|
||||
CheckAddressText(2, "255.255.255.255");
|
||||
CheckAddressText(28, "::1");
|
||||
|
|
|
|||
Loading…
Reference in New Issue