mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-26 03:55:37 +00:00
support for writefds,errorfds
This commit is contained in:
parent
16617d13d8
commit
d1c64ce557
@ -242,17 +242,10 @@ int IsSocket(int fd) {
|
|||||||
return (WSAGetLastError() != WSAENOTSOCK);
|
return (WSAGetLastError() != WSAENOTSOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsPipeOrFile(int fd) {
|
|
||||||
HANDLE h = (HANDLE)_get_osfhandle(fd);
|
|
||||||
DWORD t = GetFileType(h);
|
|
||||||
return (t == FILE_TYPE_PIPE || t == FILE_TYPE_DISK);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
|
int PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
|
||||||
const timeval* timeout) {
|
timeval* timeout) {
|
||||||
// note writefds,exceptfds will not work
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
fd_set sock_r, sock_w, sock_x;
|
fd_set sock_r, sock_w, sock_x;
|
||||||
FD_ZERO(&sock_r);
|
FD_ZERO(&sock_r);
|
||||||
@ -260,39 +253,41 @@ int PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se
|
|||||||
FD_ZERO(&sock_x);
|
FD_ZERO(&sock_x);
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
// Separate socket FDs
|
// Separate sockets for select()
|
||||||
for (fd = 0; fd < nfds; ++fd) {
|
for (fd = 0; fd < nfds; ++fd) {
|
||||||
if (readfds && FD_ISSET(fd, readfds) && IsSocket(fd)) {
|
if (IsSocket(fd)) {
|
||||||
FD_SET((SOCKET)_get_osfhandle(fd), &sock_r);
|
SOCKET s = (SOCKET)_get_osfhandle(fd);
|
||||||
}
|
if (readfds && FD_ISSET(fd, readfds))
|
||||||
if (writefds && FD_ISSET(fd, writefds) && IsSocket(fd)) {
|
FD_SET(s, &sock_r);
|
||||||
FD_SET((SOCKET)_get_osfhandle(fd), &sock_w);
|
if (writefds && FD_ISSET(fd, writefds))
|
||||||
}
|
FD_SET(s, &sock_w);
|
||||||
if (exceptfds && FD_ISSET(fd, exceptfds) && IsSocket(fd)) {
|
if (exceptfds && FD_ISSET(fd, exceptfds))
|
||||||
FD_SET((SOCKET)_get_osfhandle(fd), &sock_x);
|
FD_SET(s, &sock_x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = select(0, &sock_r, &sock_w, &sock_x, timeout);
|
int result = select(0, &sock_r, &sock_w, &sock_x, timeout);
|
||||||
int total_ready = result;
|
int total_ready = result;
|
||||||
|
|
||||||
// Poll pipes/files for read readiness
|
|
||||||
for (fd = 0; fd < nfds; ++fd) {
|
for (fd = 0; fd < nfds; ++fd) {
|
||||||
if (readfds && FD_ISSET(fd, readfds) && IsPipeOrFile(fd) && !IsSocket(fd)) {
|
HANDLE h = (HANDLE)_get_osfhandle(fd);
|
||||||
HANDLE h = (HANDLE)_get_osfhandle(fd);
|
DWORD type = GetFileType(h);
|
||||||
DWORD avail = 0;
|
if (type == FILE_TYPE_UNKNOWN || IsSocket(fd))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (GetFileType(h) == FILE_TYPE_PIPE) {
|
// READ check
|
||||||
|
if (readfds && FD_ISSET(fd, readfds)) {
|
||||||
|
if (type == FILE_TYPE_PIPE) {
|
||||||
|
DWORD avail = 0;
|
||||||
if (PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL) && avail > 0) {
|
if (PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL) && avail > 0) {
|
||||||
total_ready++;
|
total_ready++;
|
||||||
} else {
|
} else {
|
||||||
FD_CLR(fd, readfds);
|
FD_CLR(fd, readfds);
|
||||||
}
|
}
|
||||||
} else if (GetFileType(h) == FILE_TYPE_DISK) {
|
} else if (type == FILE_TYPE_DISK) {
|
||||||
char buf[1];
|
char tmp;
|
||||||
long pos = _lseek(fd, 0, SEEK_CUR);
|
long pos = _lseek(fd, 0, SEEK_CUR);
|
||||||
int r = _read(fd, buf, 1);
|
if (_read(fd, &tmp, 1) > 0) {
|
||||||
if (r > 0) {
|
|
||||||
_lseek(fd, pos, SEEK_SET);
|
_lseek(fd, pos, SEEK_SET);
|
||||||
total_ready++;
|
total_ready++;
|
||||||
} else {
|
} else {
|
||||||
@ -300,13 +295,58 @@ int PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WRITE check
|
||||||
|
if (writefds && FD_ISSET(fd, writefds)) {
|
||||||
|
DWORD written = 0;
|
||||||
|
char dummy = 0;
|
||||||
|
BOOL writable = FALSE;
|
||||||
|
if (type == FILE_TYPE_PIPE) {
|
||||||
|
// Try writing 0 bytes to check if it's broken
|
||||||
|
writable = WriteFile(h, &dummy, 0, &written, NULL);
|
||||||
|
} else if (type == FILE_TYPE_DISK) {
|
||||||
|
writable = true; // Disk files are always "writable"
|
||||||
|
}
|
||||||
|
if (writable) {
|
||||||
|
total_ready++;
|
||||||
|
} else {
|
||||||
|
FD_CLR(fd, writefds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXCEPTION check
|
||||||
|
if (exceptfds && FD_ISSET(fd, exceptfds)) {
|
||||||
|
DWORD err = 0, size = sizeof(err);
|
||||||
|
BOOL error_detected = false;
|
||||||
|
|
||||||
|
if (type == FILE_TYPE_PIPE) {
|
||||||
|
// Check broken pipe by trying non-blocking zero write
|
||||||
|
DWORD written;
|
||||||
|
char tmp = 0;
|
||||||
|
if (!WriteFile(h, &tmp, 0, &written, NULL)) {
|
||||||
|
DWORD e = GetLastError();
|
||||||
|
if (e == ERROR_NO_DATA || e == ERROR_BROKEN_PIPE) {
|
||||||
|
error_detected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_detected) {
|
||||||
|
total_ready++;
|
||||||
|
} else {
|
||||||
|
FD_CLR(fd, exceptfds);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return total_ready;
|
return total_ready;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// POSIX: just use select directly
|
// return select(nfds, readfds, writefds, exceptfds, timeout);
|
||||||
return select(nfds, readfds, writefds, exceptfds, timeout);
|
// nfds is shared with pipes , sockets , files in which we use separate maps so it can't work
|
||||||
|
// like this
|
||||||
|
LOG_ERROR(Lib_Net, "unimplemented (suck it linux) nfds={}", nfds);
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
Loading…
Reference in New Issue
Block a user