Reading Bitcoin source code 4

In the last AppInit, read the AppInitBasicSetup function, the function of this function is to register the corresponding message and processing

1. If it is a Microsoft VS environment, turn off the noise of the Microsoft stack dump through _CrtSetReportMode and _CrtSetReportFile,
_CrtSetReportMode sets the message processing method, this time set the message level to WARN, and output to file,
_CrtSetReportFile sets the message output file, Set to NUL here to ignore the message.
The _set_abort_behavior function specifies the behavior when the program terminates abnormally. Use this function to throw the exception to the exception catching function.
Reference: 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. The following code is for DEP (Data Execution Prevention, data execution protection) in winows 32-bit system. The minimum supported os system version is WinXP SP3, WinVista> = SP1, Win Server 2008, it does not matter if the setting fails , No further attention is required.
Because the winbase.h limit in GCC _WIN32_WINNT> = 0x0601 (Windows 7) will enable DEP, so it is mandatory here.
Define a function pointer to SetProcessDEPPolicy and set 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. Setup Networking initializes windows sockets

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

The implementation is as follows.
The program that uses Socket in the win32 system must call the WSAStartup function before using Socket. After that, the application can call other socket functions in the requested socket library. When an application calls the WSAStartup function, the operating system searches for the corresponding Socket library according to the requested Socket version, and then binds the found Socket library to the application. After that, the application can call other socket functions in the requested socket library. This function returns 0 after successful execution.
Example: If a program wants to use the 2.2 version of Socket, then the program code is as follows
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. On non-win32 systems, if the -sysperms parameter is set to false, the umask is set to 077. When the SIGTERM and SIGINT signals are encountered, the close flag is set to true. When the SIGHUP terminal signal is hung up, the debuglog and SIGPIPE signals are re-enabled It is ignored, otherwise if the client terminates abnormally, the daemon process will also stop running.

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

SIGTERM terminates the process software termination signal
SIGTERM is the default signal sent to the process by kill or killall commands. It will cause the termination of a process, but the SIGKILL signal is different, it can be captured and interpreted (or ignored) the process. Therefore, SIGTERM is similar to asking whether a process can be terminated, allowing files to be cleaned and closed. For this reason, during the shutdown of many Unix systems, the initialization problem SIGTERM to all non-essential power-off process, wait for a few seconds, and then issue SIGKILL to force termination. Any such process still exists.

SIGINT terminates the process and interrupts the process. In
line with the POSIX platform, the signal intelligence is controlled by its terminal. When the user wishes to interrupt the process, the signal is sent to the process. Usually ctrl-C, but on some systems, the "delete" character or "break" key-when the user of the process control terminal presses the key SIGINT to interrupt the running process is sent.

SIGHUP terminates the process. The terminal line hangs up
. The process organization structure in UNIX is that a session contains a foreground process group and one or more background process groups. A process group contains multiple processes. A session may have a session first process, and a session first process may have a control terminal. A process group may have a process group first process. The process ID of the first process of the process group is equal to the process group ID. There may be here, but under certain circumstances it is not. The process interacting with the terminal is the foreground process, otherwise it is the background process.

SIGPIPE: Broken pipe: write data to a pipe without a read end. The default action is to terminate the process.

#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, set_new_handler function

    std::set_new_handler(new_handler_terminate);
    return true;

The set_new_handler function is defined as follows
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; // C ++ 11
function description
(1) set_new_handler function The function is to set the function pointed to by new_p as the processing function called when the new operation or new [] operation fails.

(2) The set processing function can try to make more space allocatable, so that a new operation may be successful. It will return if and only if the function successfully obtains more free space; otherwise it will throw a bad_alloc exception (or a subclass that inherits the exception) or terminate the program (such as calling abort or exit).

(3) If the set processing function returns (for example, the function successfully obtains more free space), it may be called repeatedly until the memory allocation succeeds, or it does not return, or is replaced by other functions.

(4) When the processing function has not been set with set_new_handler or the set processing function is empty, the default processing function will be called. This function throws a bad_alloc exception when the memory allocation fails.
Reference: http://blog.csdn.net/wzxq123/article/details/51502356

The new_handler_terminate function is defined as follows, without throwing the std :: bad-alloc exception, and directly terminating the process, thereby avoiding possible data conflicts.

[[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();
};
Published 30 original articles · praised 74 · 230,000 views +

Guess you like

Origin blog.csdn.net/ruiyiin/article/details/104633296