Lectura del código fuente 4 de Bitcoin

En el último AppInit, lea la función AppInitBasicSetup, la función de esta función es registrar el mensaje correspondiente y el método de procesamiento

1. Si se trata de un entorno Microsoft VS, apague el ruido del volcado de la pila de Microsoft a través de _CrtSetReportMode y _CrtSetReportFile,
_CrtSetReportMode establece el método de procesamiento de mensajes, esta vez establezca el nivel de mensaje en WARN y la salida a un archivo,
_CrtSetReportFile establece el archivo de salida del mensaje, Establezca aquí NUL para ignorar el mensaje.
La función _set_abort_behavior especifica el comportamiento cuando el programa termina anormalmente. Use esta función para lanzar la excepción a la función de captura de excepciones.
Referencia: https://technet.microsoft.com/zh-cn/library/1y71x448.aspx/
https: // msdn. microsoft.com/en-us/library/e631wekh.aspx


    // ********************************************************* Step 1: setup
#ifdef _MSC_VER
    // Turn off Microsoft heap dump noise
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0));
    // Disable confusing "helpful" text message on abort, Ctrl-C
    _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif

2. El siguiente código es para DEP (Prevención de ejecución de datos, protección de ejecución de datos) en el sistema winows de 32 bits. La versión mínima del sistema operativo compatible es WinXP SP3, WinVista> = SP1, Win Server 2008, no importa si la configuración falla No se requiere más atención.
Debido a que el límite winbase.h en GCC _WIN32_WINNT> = 0x0601 (Windows 7) habilitará DEP, por lo que es obligatorio aquí.
Defina un puntero de función para SetProcessDEPPolicy y establezca DEP.

#ifdef WIN32
    // Enable Data Execution Prevention (DEP)
    // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
    // A failure is non-critical and needs no further attention!
#ifndef PROCESS_DEP_ENABLE
    // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
    // which is not correct. Can be removed, when GCCs winbase.h is fixed!
#define PROCESS_DEP_ENABLE 0x00000001
#endif
    typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD);
    PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy");
    if (setProcDEPPol != nullptr) setProcDEPPol(PROCESS_DEP_ENABLE);
#endif

3. Configurar la red inicializa los enchufes de Windows

    if (!SetupNetworking())
        return InitError("Initializing networking failed");

La implementación es la siguiente:
el programa que usa Socket en el sistema win32 debe llamar a la función WSAStartup antes de usar Socket. Después de eso, la aplicación puede llamar a otras funciones de socket en la biblioteca de socket solicitada. Cuando una aplicación llama a la función WSAStartup, el sistema operativo busca la biblioteca de Socket correspondiente de acuerdo con la versión de Socket solicitada, y luego vincula la biblioteca de Socket encontrada a la aplicación. Después de eso, la aplicación puede llamar a otras funciones de socket en la biblioteca de socket solicitada. Esta función devuelve 0 después de una ejecución exitosa.
Ejemplo: si un programa quiere usar la versión 2.2 de Socket, entonces el código del programa es el siguiente
wVersionRequested = MAKEWORD (2, 2);
err = WSAStartup (wVersionRequested, & wsaData);

bool SetupNetworking()
{
#ifdef WIN32
    // Initialize Windows Sockets
    WSADATA wsadata;
    int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
    if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
        return false;
#endif
    return true;
}

4. En sistemas que no son win32, si el parámetro -sysperms se establece en falso, la máscara de usuario se establece en 077. Cuando se encuentran las señales SIGTERM y SIGINT, el indicador de cierre se establece en verdadero. Se ignora; de lo contrario, si el cliente finaliza de manera anormal, el proceso del demonio también dejará de ejecutarse.

static void HandleSIGTERM(int)
{
    fRequestShutdown = true;
}
static void HandleSIGHUP(int)
{
    fReopenDebugLog = true;
}

SIGTERM finaliza la señal de finalización del software del proceso
SIGTERM es la señal predeterminada enviada al proceso mediante comandos kill o killall. Causará la terminación de un proceso, pero la señal SIGKILL es diferente, se puede capturar e interpretar (o ignorar) el proceso. Por lo tanto, SIGTERM es similar a preguntar si un proceso puede finalizarse, permitiendo que los archivos se limpien y se cierren. Por esta razón, durante el apagado de muchos sistemas Unix, inicializando el problema SIGTERM a todos los procesos de apagado no esenciales, espere unos segundos y luego emita SIGKILL para terminar forzosamente cualquier proceso que todavía exista.

SIGINT finaliza el proceso e interrumpe el proceso. En
línea con la plataforma POSIX, la inteligencia de la señal es controlada por su terminal. Cuando el usuario desea interrumpir el proceso, la señal se envía al proceso. Por lo general, Ctrl-C, pero en algunos sistemas, el carácter "eliminar" o la tecla "interrumpir" cuando el usuario del terminal de control del proceso presiona la tecla SIGINT para interrumpir el proceso en ejecución.

SIGHUP finaliza el proceso. La línea de terminal se cuelga
. La estructura de organización del proceso en UNIX es que una sesión contiene un grupo de procesos en primer plano y uno o más grupos de procesos en segundo plano. Un grupo de procesos contiene múltiples procesos. Una sesión puede tener un primer proceso de sesión, y un primer proceso de sesión puede tener un terminal de control. Un grupo de procesos puede tener un primer proceso de grupo de procesos. La ID del proceso del primer proceso del grupo de procesos es igual a la ID del grupo de procesos. Puede haber aquí, pero en ciertas circunstancias no lo es. El proceso que interactúa con el terminal es el proceso en primer plano, de lo contrario es el proceso en segundo plano.

SIGPIPE: tubería rota: escribe datos en una tubería sin un final de lectura. La acción predeterminada es terminar el proceso.

#ifndef WIN32
   if (!gArgs.GetBoolArg("-sysperms", false)) {
       umask(077);
   }

   // Clean shutdown on SIGTERM
   registerSignalHandler(SIGTERM, HandleSIGTERM);
   registerSignalHandler(SIGINT, HandleSIGTERM);

   // Reopen debug.log on SIGHUP
   registerSignalHandler(SIGHUP, HandleSIGHUP);

   // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
   signal(SIGPIPE, SIG_IGN);
#endif

5, función set_new_handler

    std::set_new_handler(new_handler_terminate);
    return true;

La función set_new_handler se define de la siguiente manera
Typedef void (* new_handler) ();
new_handler set_new_handler (new_handler new_p) throw (); // C ++ 98
new_handler set_new_handler (new_handler new_p) noexcept; //
Descripción de la función C ++ 11
(1) set_new_handler La función es establecer la función señalada por new_p como la función de procesamiento llamada cuando falla la nueva operación o la nueva operación [].

(2) La función de procesamiento de conjunto puede intentar hacer que se asigne más espacio, de modo que una nueva operación pueda tener éxito. Volverá si y solo si la función obtiene más espacio libre; de ​​lo contrario, arrojará una excepción bad_alloc (o una subclase que herede la excepción) o terminará el programa (como llamar a abortar o salir).

(3) Si la función de procesamiento establecida regresa (por ejemplo, la función obtiene con éxito más espacio libre), se puede llamar repetidamente hasta que la asignación de memoria tenga éxito, o no regrese o se reemplace por otras funciones.

(4) Cuando la función de procesamiento no se ha establecido con set_new_handler, o la función de procesamiento establecida está vacía, se llamará a la función de procesamiento predeterminada. Esta función genera una excepción bad_alloc cuando falla la asignación de memoria.
Referencia: http://blog.csdn.net/wzxq123/article/details/51502356

La función new_handler_terminate se define de la siguiente manera, sin lanzar la excepción std :: bad-alloc y terminar directamente el proceso, evitando así posibles conflictos de datos.

[[noreturn]] static void new_handler_terminate()
{
    // Rather than throwing std::bad-alloc if allocation fails, terminate
    // immediately to (try to) avoid chain corruption.
    // Since LogPrintf may itself allocate memory, set the handler directly
    // to terminate first.
    std::set_new_handler(std::terminate);
    LogPrintf("Error: Out of memory. Terminating.\n");

    // The log was successful, terminate now.
    std::terminate();
};
30 artículos originales publicados · elogiados 74 · 230,000 vistas +

Supongo que te gusta

Origin blog.csdn.net/ruiyiin/article/details/104633296
Recomendado
Clasificación