static int doParent()

in src/tools/closetest/closetest.cpp [664:841]


static int doParent(std::deque<std::wstring> argv)
{
    int numBatches = 4;
    int dir = 0;
    bool useJob = false;
    bool useGapProcess = false;
    int allocChunk = 0;
    bool useSiblings = false;
    bool noRealloc = false;

    // Parse arguments
    shift(argv); // discard the program name.
    while (!argv.empty())
    {
        const auto arg = shift(argv);
        const auto hasNext = !argv.empty();

        if (arg == L"--help" || arg == L"-h")
        {
            usage();
            exit(0);
        }
        else if (arg == L"-n" && hasNext)
        {
            numBatches = shiftInt(argv);
        }
        else if (arg == L"-d" && hasNext)
        {
            const auto next = shift(argv);
            if (next == L"forward")
            {
                dir = 1;
            }
            else if (next == L"backward")
            {
                dir = 2;
            }
            else if (next == L"alternate")
            {
                dir = 3;
            }
            else if (next == L"none")
            {
                dir = 0;
            }
            else
            {
                fprintf(stderr, "error: unrecognized -d argument: %ls\n", next.c_str());
                exit(1);
            }
        }
        else if (arg == L"--gap")
        {
            useGapProcess = true;
        }
        else if (arg == L"--no-gap")
        {
            useGapProcess = false;
        }
        else if (arg == L"--alloc" && hasNext)
        {
            const auto next = shift(argv);
            allocChunk = (int)(_wtof(next.c_str()) * 1024.0 * 1024.0);
        }
        else if (arg == L"-m" && hasNext)
        {
            const auto next = shift(argv);
            if (next == L"pipe")
            {
                useJob = false;
            }
            else if (next == L"job")
            {
                useJob = true;
            }
            else
            {
                fprintf(stderr, "error: unrecognized -m argument: %ls\n", next.c_str());
                exit(1);
            }
        }
        else if (arg == L"--graph" && hasNext)
        {
            const auto next = shift(argv);
            if (next == L"tree")
            {
                useSiblings = false;
            }
            else if (next == L"list")
            {
                useSiblings = true;
            }
            else
            {
                fprintf(stderr, "error: unrecognized --graph argument: %ls\n", next.c_str());
                exit(1);
            }
        }
        else if (arg == L"--log" && hasNext)
        {
            const auto next = shift(argv);
            std::wstring pipename(L"\\\\.\\pipe\\");
            pipename.append(next);

            g_hLogging = CreateFileW(pipename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
            if (g_hLogging != INVALID_HANDLE_VALUE)
            {
                g_pipestr = next;
            }
            else
            {
                fprintf(stderr, "error: pipe cannot be opened: %ls\n", next.c_str());
                exit(1);
            }
        }
        else if (arg == L"--delay" && hasNext)
        {
            const auto next = shift(argv);
            const long ms = std::stol(next);
            std::this_thread::sleep_for(std::chrono::milliseconds(ms));
        }
        else if (arg == L"--no-realloc")
        {
            noRealloc = true;
        }
        else
        {
            usage();
            fprintf(stderr, "\nerror: unrecognized argument: %ls\n", arg.c_str());
            exit(1);
        }
    }

    // Decide which children to start.
    std::vector<std::wstring> spawnList;
    std::vector<HANDLE> handles;
    for (int i = 0; i < numBatches; ++i)
    {
        if (dir == 0)
        {
            genChild(i + 1, L"", allocChunk, spawnList);
        }
        if (dir & 1)
        {
            genBatch(true, useJob, useGapProcess, allocChunk, spawnList, handles);
        }
        if (dir & 2)
        {
            genBatch(false, useJob, useGapProcess, allocChunk, spawnList, handles);
        }
    }

    // Spawn the children.
    if (!noRealloc)
    {
        FreeConsole();
        AllocConsole();
    }

    if (useSiblings)
    {
        spawnSiblings(GetCurrentProcessId(), spawnList);
    }
    else
    {
        spawnChildTree(GetCurrentProcessId(), spawnList);
    }
    for (auto h : handles)
    {
        CloseHandle(h);
    }

    // Wait until we're killed.
    dumpConsoleProcessList();
    Sleep(300 * 1000);

    return 0;
}