From ff71726ff046b960e6b2bce9d150d7e8b0bf6cdb Mon Sep 17 00:00:00 2001 From: shenlei Date: Wed, 30 Sep 2026 12:31:04 +0900 Subject: [PATCH] Port PythonExceptionSender and install it at boot as 40250 Main does Co-Authored-By: Claude Opus 5.5 --- audit/history.jsonl | 1 + .../PythonExceptionSender.cpp.json | 29 ++++++++ src/platform/ScriptLib/PythonBoot.cpp | 8 +++ src/port/ScriptLib/StdAfx.cpp | 10 +++ .../UserInterface/PythonExceptionSender.cpp | 67 +++++++++++++++++++ .../UserInterface/PythonExceptionSender.h | 13 ++++ 6 files changed, 128 insertions(+) create mode 100644 audit/port-map/UserInterface/PythonExceptionSender.cpp.json create mode 100644 src/port/ScriptLib/StdAfx.cpp create mode 100644 src/port/UserInterface/PythonExceptionSender.cpp create mode 100644 src/port/UserInterface/PythonExceptionSender.h diff --git a/audit/history.jsonl b/audit/history.jsonl index 8231fb5c..8ee9a755 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -595,3 +595,4 @@ {"date": "2026-09-30T03:27:19+00:00", "unit": "EterLib/GrpPixelShader.cpp", "action": "all functions N_A: CPixelShader has no user outside its own files", "evidence": "grep CPixelShader over ClientVS22/source"} {"date": "2026-09-30T03:27:19+00:00", "unit": "EterLib/GrpVertexShader.cpp", "action": "all functions N_A: CVertexShader has no user outside its own files", "evidence": "grep CVertexShader over ClientVS22/source"} {"date": "2026-09-30T03:27:19+00:00", "unit": "EterLib/GrpD3DXBuffer.cpp", "action": "all functions N_A: CDirect3DXBuffer is used only by the unused CPixelShader/CVertexShader", "evidence": "grep CDirect3DXBuffer over ClientVS22/source"} +{"date": "2026-09-30T03:31:03+00:00", "unit": "UserInterface/PythonExceptionSender.cpp", "action": "PORTED: verbatim copy + ScriptLib/StdAfx.cpp SetExceptionSender; PythonBoot installs the sender as 40250 Main does", "evidence": "iconv copy of ClientVS22/source/UserInterface/PythonExceptionSender.{h,cpp} and ScriptLib/StdAfx.cpp; ctest 19/19"} diff --git a/audit/port-map/UserInterface/PythonExceptionSender.cpp.json b/audit/port-map/UserInterface/PythonExceptionSender.cpp.json new file mode 100644 index 00000000..44a6eea2 --- /dev/null +++ b/audit/port-map/UserInterface/PythonExceptionSender.cpp.json @@ -0,0 +1,29 @@ +{ + "reference": "UserInterface/PythonExceptionSender.cpp", + "reference_sha256": "8e32cdd2631e1b206a11953a9bcb865d73b7cabbc73710586902b0e54b935b74", + "priority": "P4", + "contracts": [], + "functions": { + "CPythonExceptionSender::Send": { + "status": "PORTED", + "impl": [ + "src/port/UserInterface/PythonExceptionSender.cpp:CPythonExceptionSender::Send" + ], + "note": "verbatim 40250 source (Send body is all comments); installed by PythonBoot::Boot like 40250 Main, with ScriptLib/StdAfx.cpp SetExceptionSender" + }, + "CPythonExceptionSender::CPythonExceptionSender": { + "status": "PORTED", + "impl": [ + "src/port/UserInterface/PythonExceptionSender.cpp:CPythonExceptionSender::CPythonExceptionSender" + ], + "note": "verbatim 40250 source (Send body is all comments); installed by PythonBoot::Boot like 40250 Main, with ScriptLib/StdAfx.cpp SetExceptionSender" + }, + "CPythonExceptionSender::~CPythonExceptionSender": { + "status": "PORTED", + "impl": [ + "src/port/UserInterface/PythonExceptionSender.cpp:CPythonExceptionSender::~CPythonExceptionSender" + ], + "note": "verbatim 40250 source (Send body is all comments); installed by PythonBoot::Boot like 40250 Main, with ScriptLib/StdAfx.cpp SetExceptionSender" + } + } +} diff --git a/src/platform/ScriptLib/PythonBoot.cpp b/src/platform/ScriptLib/PythonBoot.cpp index 7dcde07c..e9105ec0 100644 --- a/src/platform/ScriptLib/PythonBoot.cpp +++ b/src/platform/ScriptLib/PythonBoot.cpp @@ -14,6 +14,7 @@ #include "../EterLib/HostCursor.h" #include "UserInterface/PythonNetworkStream.h" #include "UserInterface/AccountConnector.h" +#include "UserInterface/PythonExceptionSender.h" #include "UserInterface/ServerStateChecker.h" #include "UserInterface/PythonPlayer.h" #include "GameLib/FlyingObjectManager.h" @@ -70,6 +71,8 @@ namespace { // 40250 has this on Main()'s stack. CPythonLauncher is a CSingleton, so there is still only ever one. std::unique_ptr g_launcher; +// 40250 Main(): CPythonExceptionSender pyExceptionSender; SetExceptionSender(&pyExceptionSender); +std::unique_ptr g_exception_sender; std::unique_ptr g_window_manager; std::unique_ptr g_resource; // 40250 CPythonApplication::m_timer; CSlotWindow's cool time and Process() read it via Instance(). @@ -733,6 +736,8 @@ bool Start(const char* stdlib_path, std::string* error) PythonHost::Configure(); g_launcher = std::make_unique(); // Py_Initialize + g_exception_sender = std::make_unique(); + SetExceptionSender(g_exception_sender.get()); // The script fiber (RunMainScript) is a second OS thread; 2.7 creates the GIL lazily. PyEval_InitThreads(); if (!g_launcher->Create()) @@ -1071,6 +1076,9 @@ void Stop() g_window_manager.reset(); g_resource.reset(); g_timer.reset(); + // PORT: 40250 leaves g_pkExceptionSender dangling once Main() returns; Boot can run again here. + SetExceptionSender(NULL); + g_exception_sender.reset(); g_launcher.reset(); } diff --git a/src/port/ScriptLib/StdAfx.cpp b/src/port/ScriptLib/StdAfx.cpp new file mode 100644 index 00000000..0bc78024 --- /dev/null +++ b/src/port/ScriptLib/StdAfx.cpp @@ -0,0 +1,10 @@ +// stdafx.cpp : source file that includes just the standard includes +// scriptLib.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "StdAfx.h" + +void SetExceptionSender(IPythonExceptionSender * pkExceptionSender) +{ + g_pkExceptionSender = pkExceptionSender; +} diff --git a/src/port/UserInterface/PythonExceptionSender.cpp b/src/port/UserInterface/PythonExceptionSender.cpp new file mode 100644 index 00000000..b5f0f67f --- /dev/null +++ b/src/port/UserInterface/PythonExceptionSender.cpp @@ -0,0 +1,67 @@ +#include "StdAfx.h" +#include "PythonExceptionSender.h" + +void CPythonExceptionSender::Send() +{ + //DWORD dwCRC32 = GetCaseCRC32(m_strExceptionString.c_str(), m_strExceptionString.length()); + //if (m_kSet_dwSendedExceptionCRC.end() != m_kSet_dwSendedExceptionCRC.find(dwCRC32)) + // return; + + //TraceError("%s", m_strExceptionString.c_str()); + + //SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + //if (s==INVALID_SOCKET) + //{ + // Tracef(" CPythonExceptionSender::Send() - Invalid Socket"); + //} + + + //DWORD arg = 1; + //ioctlsocket(s, FIONBIO, &arg); // Non-blocking mode + + //char szServerAddr[256]; + //int nServerPort; + //strncpy(szServerAddr, "211.105.222.20", sizeof(szServerAddr)-1); + + //nServerPort=LocaleService_GetPythonErrorReportPort(); + // + //sockaddr_in sa; + //sa.sin_family = AF_INET; + //sa.sin_port = htons(nServerPort); + //sa.sin_addr.s_addr = inet_addr(szServerAddr); + //if (connect(s,(sockaddr*)&sa,sizeof(sa))) + // return; + + //int number_ticket=0; + //if (recv(s,(char*)&number_ticket,4,0)) + // return; + + //int length=m_strExceptionString.length(); + //int total=0; + //int ret=0; + + //int count = 100; + //while(count--) + //{ + // // send plain text + // ret = send(s,(char*)(&m_strExceptionString[0])+total,length-total,0); + // + // if (ret<0) + // break; + + // total+=ret; + // if (total>=length) + // break; + //} + //closesocket(s); + + //m_kSet_dwSendedExceptionCRC.insert(dwCRC32); +} + +CPythonExceptionSender::CPythonExceptionSender() +{ +} +CPythonExceptionSender::~CPythonExceptionSender() +{ +} diff --git a/src/port/UserInterface/PythonExceptionSender.h b/src/port/UserInterface/PythonExceptionSender.h new file mode 100644 index 00000000..0aa331e9 --- /dev/null +++ b/src/port/UserInterface/PythonExceptionSender.h @@ -0,0 +1,13 @@ +#pragma once + +class CPythonExceptionSender : public IPythonExceptionSender +{ + public: + CPythonExceptionSender(); + virtual ~CPythonExceptionSender(); + + void Send(); + + protected: + std::set m_kSet_dwSendedExceptionCRC; +};