mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Merge pull request #22386 from hrydgard/adhoc-shutdown-race
Adhoc: Fix shutdown hanging when it comes right after adhoc init
This commit is contained in:
6 files changed
+37
-7
No files matched your search
@@ -45,3 +45,4 @@ u32 matchingThreadHackAddr = 0;
|
||||
u32_le matchingThreadCode[3];
|
||||
|
||||
bool g_adhocServerConnected = false;
|
||||
std::atomic<bool> g_adhocServerLoginFailed(false);
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "CommonTypes.h"
|
||||
#include "Swap.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
extern u32 dummyThreadHackAddr;
|
||||
@@ -52,5 +53,8 @@ extern u32 matchingThreadHackAddr;
|
||||
extern u32_le matchingThreadCode[3];
|
||||
|
||||
extern bool g_adhocServerConnected;
|
||||
// Set by the friend finder when its attempt to connect and log in for the latest login request
|
||||
// failed, so a caller waiting on that login can stop waiting.
|
||||
extern std::atomic<bool> g_adhocServerLoginFailed;
|
||||
|
||||
constexpr u32 defaultLastRecvDelta = 10000; //10000 usec worked well for games published by Falcom (ie. Ys vs Sora Kiseki, Vantage Master Portable)
|
||||
+12
-2
@@ -1401,8 +1401,7 @@ int friendFinder() {
|
||||
}
|
||||
g_adhocServerIP.in.sin_port = htons(SERVER_PORT);
|
||||
|
||||
// Finder Loop
|
||||
friendFinderRunning = true;
|
||||
// Finder Loop. The flag was set by whoever started us, and cleared to stop us.
|
||||
while (friendFinderRunning) {
|
||||
// Acquire Network Lock
|
||||
//_acquireNetworkLock();
|
||||
@@ -1421,6 +1420,7 @@ int friendFinder() {
|
||||
}
|
||||
else {
|
||||
g_adhocServerConnected = false;
|
||||
g_adhocServerLoginFailed = true;
|
||||
shutdown((int)metasocket, SD_BOTH);
|
||||
closesocket((int)metasocket);
|
||||
metasocket = (int)INVALID_SOCKET;
|
||||
@@ -2252,6 +2252,16 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
return iResult;
|
||||
|
||||
done = (IsSocketReady((int)metasocket, false, true) > 0);
|
||||
if (done) {
|
||||
// Writable can also mean the attempt failed (refused, say). Then there's no point
|
||||
// waiting out the timeout.
|
||||
int soError = 0;
|
||||
socklen_t soErrorLen = sizeof(soError);
|
||||
if (getsockopt((int)metasocket, SOL_SOCKET, SO_ERROR, (char *)&soError, &soErrorLen) == 0 && soError != 0) {
|
||||
errorcode = soError;
|
||||
break;
|
||||
}
|
||||
}
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinlen = sizeof(sin);
|
||||
memset(&sin, 0, sinlen);
|
||||
|
||||
@@ -1865,9 +1865,7 @@ int create_listen_socket(uint16_t port)
|
||||
*/
|
||||
int server_loop(int server)
|
||||
{
|
||||
// Set Running Status
|
||||
//_status = 1;
|
||||
adhocServerRunning = true;
|
||||
// adhocServerRunning was set by whoever started the thread, and is cleared to stop it.
|
||||
|
||||
// Create Empty Status Logfile
|
||||
update_status();
|
||||
|
||||
@@ -560,7 +560,8 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) {
|
||||
}
|
||||
|
||||
// Retry until successfully sent. Login packet sent after successfully connected to Adhoc Server (indicated by networkInited), so we're not sending Login again here
|
||||
if ((req.opcode == OPCODE_LOGIN && !g_adhocServerConnected) || (ret == SOCKET_ERROR && (sockerr == EAGAIN || sockerr == EWOULDBLOCK))) {
|
||||
// A login stops waiting early once the friend finder has tried and failed to connect.
|
||||
if ((req.opcode == OPCODE_LOGIN && !g_adhocServerConnected && !g_adhocServerLoginFailed) || (ret == SOCKET_ERROR && (sockerr == EAGAIN || sockerr == EWOULDBLOCK))) {
|
||||
u64 now = (u64)(time_now_d() * 1000000.0);
|
||||
if (now - adhocctlStartTime <= static_cast<u64>(adhocDefaultTimeout) + 500) {
|
||||
// Try again in another 0.5ms until timedout.
|
||||
@@ -1921,9 +1922,14 @@ void __NetAdhocInit() {
|
||||
__AdhocNotifInit();
|
||||
__AdhocServerInit();
|
||||
|
||||
// Create built-in AdhocServer Thread
|
||||
// Create built-in AdhocServer Thread. The flag is set here rather than by the thread, so that a
|
||||
// shutdown that clears it before the thread gets going can't be undone (see friendFinder).
|
||||
adhocServerRunning = false;
|
||||
if (adhocServerThread.joinable()) {
|
||||
adhocServerThread.join();
|
||||
}
|
||||
if (g_Config.bEnableWlan && g_Config.bEnableAdhocServer) {
|
||||
adhocServerRunning = true;
|
||||
adhocServerThread = std::thread(proAdhocServerThread, SERVER_PORT);
|
||||
}
|
||||
}
|
||||
@@ -1996,6 +2002,7 @@ int sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
|
||||
|
||||
adhocctlEvents.clear();
|
||||
netAdhocctlInited = true; //needed for cleanup during AdhocctlTerm even when it failed to connect to Adhoc Server (since it's being faked as success)
|
||||
g_adhocServerLoginFailed = false;
|
||||
isAdhocctlNeedLogin = true;
|
||||
|
||||
// Create fake PSP Thread for callback
|
||||
@@ -2008,6 +2015,12 @@ int sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
|
||||
|
||||
// TODO: Merging friendFinder (real) thread to AdhocThread (fake) thread on PSP side
|
||||
if (!friendFinderRunning) {
|
||||
// Set before the thread starts, not by it: shutting down before it got going used to clear
|
||||
// the flag first, and then the thread set it again and never stopped, hanging the join.
|
||||
if (friendFinderThread.joinable()) {
|
||||
friendFinderThread.join();
|
||||
}
|
||||
friendFinderRunning = true;
|
||||
friendFinderThread = std::thread(friendFinder);
|
||||
}
|
||||
|
||||
@@ -3180,6 +3193,7 @@ int sceNetAdhocctlScan() {
|
||||
// Only scan when in Disconnected state, otherwise AdhocServer will kick you out
|
||||
if (adhocctlState == ADHOCCTL_STATE_DISCONNECTED && !isAdhocctlBusy) {
|
||||
isAdhocctlBusy = true;
|
||||
g_adhocServerLoginFailed = false;
|
||||
isAdhocctlNeedLogin = true;
|
||||
adhocctlState = ADHOCCTL_STATE_SCANNING;
|
||||
adhocctlCurrentMode = ADHOCCTL_MODE_NORMAL;
|
||||
@@ -3673,6 +3687,7 @@ int NetAdhocctl_Create(const char *groupName) {
|
||||
// Disconnected State
|
||||
if (adhocctlState == ADHOCCTL_STATE_DISCONNECTED && !isAdhocctlBusy) {
|
||||
isAdhocctlBusy = true;
|
||||
g_adhocServerLoginFailed = false;
|
||||
isAdhocctlNeedLogin = true;
|
||||
|
||||
// Set Network Name
|
||||
|
||||
@@ -903,6 +903,8 @@ int main(int argc, const char* argv[]) {
|
||||
g_Config.bMemStickInserted = true;
|
||||
g_Config.iMemStickSizeGB = 16;
|
||||
g_Config.bEnableWlan = true;
|
||||
// The net tests want WLAN on, but a test run shouldn't depend on reaching a real adhoc server.
|
||||
g_Config.sProAdhocServer = "localhost";
|
||||
g_Config.sMACAddress = "12:34:56:78:9A:BC";
|
||||
g_Config.iFirmwareVersion = PSP_DEFAULT_FIRMWARE;
|
||||
g_Config.iPSPModel = PSP_MODEL_SLIM;
|
||||
|
||||
Reference in new issue
Block a user