upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui.cpp91
-rw-r--r--src/main_gui.cpp8
2 files changed, 69 insertions, 30 deletions
diff --git a/src/gui.cpp b/src/gui.cpp
index 672f0ff..296d20c 100644
--- a/src/gui.cpp
+++ b/src/gui.cpp
@@ -1410,63 +1410,94 @@ static bool g_wizardConverted = false;
1410static int g_restartArgc = 0; 1410static int g_restartArgc = 0;
1411static char** g_restartArgv = NULL; 1411static char** g_restartArgv = NULL;
1412 1412
1413#ifdef _WIN32
1414// Quote one argument so CommandLineToArgvW parses it back to exactly this
1415// string: only backslashes that immediately precede a double quote (including
1416// the closing one) are doubled, so ordinary Windows paths are not mangled.
1417static std::string QuoteArgWin(const std::string& a)
1418{
1419 if (!a.empty() && a.find_first_of(" \t\"") == std::string::npos)
1420 return a;
1421 std::string r = "\"";
1422 size_t bs = 0;
1423 for (size_t i = 0; i < a.size(); i++)
1424 {
1425 if (a[i] == '\\') { bs++; continue; }
1426 if (a[i] == '"') { r.append(bs * 2 + 1, '\\'); r += '"'; bs = 0; continue; }
1427 r.append(bs, '\\'); bs = 0; r += a[i];
1428 }
1429 r.append(bs * 2, '\\');
1430 r += "\"";
1431 return r;
1432}
1433#endif
1434
1413// Relaunch Bitflash with the same arguments and datadir, then ask this instance 1435// Relaunch Bitflash with the same arguments and datadir, then ask this instance
1414// to exit. A short delay lets the old process release the network port and the 1436// to exit -- but only once the relaunch has actually started, so a failure never
1415// block-index files before the new one opens them, so mining resumes cleanly on 1437// leaves the user with no node running. The new instance waits (-restartwait)
1416// the SQLite wallet instead of both instances fighting over the same files. 1438// before it opens the network port and the block index, so this one is gone
1439// first and they never fight over the same files.
1417static void RestartApplication() 1440static void RestartApplication()
1418{ 1441{
1442 bool fLaunched = false;
1419#ifdef _WIN32 1443#ifdef _WIN32
1420 char exePath[MAX_PATH]; 1444 char exePath[MAX_PATH];
1421 if (GetModuleFileNameA(NULL, exePath, MAX_PATH) == 0) 1445 if (GetModuleFileNameA(NULL, exePath, MAX_PATH) == 0)
1422 return; 1446 return;
1423 std::string strArgs; 1447 std::string strCmd = QuoteArgWin(exePath);
1424 bool fHasDataDir = false; 1448 bool fHasDataDir = false;
1425 for (int i = 1; i < g_restartArgc; i++) 1449 for (int i = 1; i < g_restartArgc; i++)
1426 { 1450 {
1427 std::string a = g_restartArgv[i] ? g_restartArgv[i] : ""; 1451 std::string a = g_restartArgv[i] ? g_restartArgv[i] : "";
1428 if (a.find("-datadir=") == 0 || a.find("/datadir=") == 0) 1452 if (a.find("-datadir=") == 0 || a.find("/datadir=") == 0)
1429 fHasDataDir = true; 1453 fHasDataDir = true;
1430 strArgs += " \"" + a + "\""; 1454 strCmd += " " + QuoteArgWin(a);
1431 } 1455 }
1432 if (!fHasDataDir) 1456 if (!fHasDataDir)
1433 strArgs += " \"-datadir=" + GetAppDir() + "\""; 1457 strCmd += " " + QuoteArgWin("-datadir=" + GetAppDir());
1434 1458 strCmd += " -restartwait";
1435 std::string strBat = GetAppDir() + "\\bitflash-restart.bat"; 1459
1436 FILE* pf = fopen(strBat.c_str(), "wb"); 1460 std::vector<char> cmdBuf(strCmd.begin(), strCmd.end());
1437 if (pf) 1461 cmdBuf.push_back('\0');
1462 STARTUPINFOA si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
1463 PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(pi));
1464 if (CreateProcessA(NULL, &cmdBuf[0], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
1438 { 1465 {
1439 // ping is the reliable no-console delay on Windows; timeout needs a tty. 1466 CloseHandle(pi.hProcess);
1440 fprintf(pf, 1467 CloseHandle(pi.hThread);
1441 "@echo off\r\n" 1468 fLaunched = true;
1442 "ping 127.0.0.1 -n 3 >nul\r\n"
1443 "start \"\" \"%s\"%s\r\n"
1444 "del \"%%~f0\"\r\n",
1445 exePath, strArgs.c_str());
1446 fclose(pf);
1447 std::string strCmd = "cmd /c \"" + strBat + "\"";
1448 STARTUPINFOA si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
1449 PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(pi));
1450 if (CreateProcessA(NULL, (char*)strCmd.c_str(), NULL, NULL, FALSE,
1451 CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
1452 {
1453 CloseHandle(pi.hProcess);
1454 CloseHandle(pi.hThread);
1455 }
1456 } 1469 }
1457#else 1470#else
1458 pid_t pid = fork(); 1471 pid_t pid = fork();
1459 if (pid == 0) 1472 if (pid == 0)
1460 { 1473 {
1474 // Child: wait for the parent to release the port and files, then re-exec.
1475 // /proc/self/exe is the reliable absolute path; argv[0] may be relative
1476 // or a bare name that execv() cannot resolve.
1461 sleep(2); 1477 sleep(2);
1478 char exePath[4096];
1479 ssize_t len = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
1480 if (len > 0)
1481 {
1482 exePath[len] = '\0';
1483 execv(exePath, g_restartArgv);
1484 }
1462 if (g_restartArgv) 1485 if (g_restartArgv)
1463 execv(g_restartArgv[0], g_restartArgv); 1486 execv(g_restartArgv[0], g_restartArgv);
1464 _exit(127); 1487 _exit(127);
1465 } 1488 }
1489 fLaunched = (pid > 0);
1466#endif 1490#endif
1467 fShutdown = true; 1491
1468 if (glfwGetCurrentContext()) 1492 if (fLaunched)
1469 glfwSetWindowShouldClose(glfwGetCurrentContext(), true); 1493 {
1494 fShutdown = true;
1495 if (glfwGetCurrentContext())
1496 glfwSetWindowShouldClose(glfwGetCurrentContext(), true);
1497 }
1498 else
1499 g_wizardStatus = "Could not relaunch automatically -- please restart "
1500 "Bitflash yourself to switch to the SQLite wallet.";
1470} 1501}
1471 1502
1472static void DrawBackendWizardDialog() 1503static void DrawBackendWizardDialog()
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 6cd8b75..55ca8c6 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -509,6 +509,14 @@ int main(int argc, char* argv[])
509 509
510 ParseStartupArguments(argc, argv); 510 ParseStartupArguments(argc, argv);
511 511
512#ifdef _WIN32
513 // Set by the GUI "Restart Now" button: give the previous instance a moment
514 // to release the network port and the block-index files before this one
515 // opens them, so a relaunch does not race the process it is replacing.
516 if (arg(argc, argv, "/restartwait") || arg(argc, argv, "-restartwait"))
517 Sleep(2500);
518#endif
519
512 // Hidden self-test helper. It must run before LoadWallet(): several 520 // Hidden self-test helper. It must run before LoadWallet(): several
513 // storage-sanity scenarios deliberately make wallet.dat unsafe to load. 521 // storage-sanity scenarios deliberately make wallet.dat unsafe to load.
514 string strSelfTestMutateWallet = 522 string strSelfTestMutateWallet =