CreateProcess problems when using PROC_THREAD_ATTRIBUTE_PREFERRED_NODE or PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY

StackOverflow https://stackoverflow.com/questions/18647965

سؤال

I keep getting error 87, ERROR_INVALID_PARAMETERS when I call CreateProcess and use the PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY extended attribute. I use the exact same code to call CreateRemoteThreadEx, and that works fine. Also, PROC_THREAD_ATTRIBUTE_PREFERRED_NODE seems to have no effect. So what am I doing wrong!?

Microsoft Windows Server 2008 R2 Enterprise, 6.1.7601 SP1 Build 7601

I even installed this service pack: A child process cannot be created by calling a CreateProcess function that uses the PROC_THREAD_ATTRIBUTE_PREFERRED_NODE parameter in Windows 7 or in Windows Server 2008 R2

Here is example code:

#include <windows.h>

typedef unsigned __int64 QWORD;

class CErr {
public:
    CErr(LPCSTR szFunc, DWORD nErr) {
        char szBuf[0x10000];
        DWORD fFlags = FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM;
        DWORD fLang =  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
        if (!nErr)
            nErr = GetLastError();
        FormatMessage(fFlags, NULL, nErr, fLang, szBuf, sizeof(szBuf) - 1, NULL);
        printf("%s: %s", szFunc, szBuf);
    }
};

int main(int argc, char* argv[])
{
    DWORD nErr;
    size_t cb;
    char sAttribsBuf[4096];
    auto pAttribs = (PPROC_THREAD_ATTRIBUTE_LIST)sAttribsBuf;

    if (!InitializeProcThreadAttributeList(NULL, 1, 0, &cb)
     && ((nErr = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)) 
        throw CErr("InitializeProcThreadAttributeList", nErr);
    if (!InitializeProcThreadAttributeList(pAttribs, 1, 0, &cb))
        throw CErr("InitializeProcThreadAttributeList", 0);

#if 1 // if enabled, CreateProcess succeeds, but doesn't set affinity 

    WORD iNuma = 1;  // WORD is the only size that does not error here
    if (!UpdateProcThreadAttribute(pAttribs, 0, PROC_THREAD_ATTRIBUTE_PREFERRED_NODE,
     &iNuma, sizeof(iNuma), NULL, NULL))
        throw CErr("UpdateProcThreadAttribute", 0);

#else // if enabled, CreateProcess fails with ERROR_INVALID_PARAMETERS(87)

    GROUP_AFFINITY GrpAffinity = { 0 };
    GrpAffinity.Mask = 1;
    if (!UpdateProcThreadAttribute(pAttribs, 0, PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY, 
     &GrpAffinity, sizeof(GrpAffinity), NULL, NULL))
        throw CErr("UpdateProcThreadAttribute", 0);

#endif

    auto fCreationFlags = EXTENDED_STARTUPINFO_PRESENT;
    PROCESS_INFORMATION pi = { 0 };                     
    STARTUPINFOEX si = { 0 };
    si.StartupInfo.cb = sizeof(si);
    si.lpAttributeList = pAttribs;
    if (!CreateProcess(NULL, "notepad.exe", NULL, NULL, false, fCreationFlags, 
     NULL, NULL, &si.StartupInfo, &pi))
        throw CErr("CreateProcess", 0);  // error if ...ATTRIBUTE_GROUP_AFFINITY

    // SetProcessAffinityMask(pi.hProcess,1);  // if enabled, notepad's affinity is set

    WaitForSingleObject(pi.hProcess, INFINITE);

    DeleteProcThreadAttributeList(pAttribs);

    return 0;
}
هل كانت مفيدة؟

المحلول

It is not clear from the documentation, but I think I figured it out. PROC_THREAD_ATTRIBUTE_PREFERRED_NODE is only supposed to be used with CreateProcess(). PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR and PROC_THREAD_ATTRIBUTE_GROUP_AFFINITY are only supposed to be used with CreateThread().

PROC_THREAD_ATTRIBUTE_PREFERRED_NODE might be setting the affinity of the process to all the processors in the same GROUP as the node. I can't verify it, since my test system only has 12 cores on two numa nodes. Setting PROC_THREAD_ATTRIBUTE_PREFERRED_NODE to 0 or to 1 sets the affinity to all the cores. I did verify that the stack of the process created by CreateProcess is located on the numa node indicated by PROC_THREAD_ATTRIBUTE_PREFERRED_NODE. Also not documented, the size of the node being passed in must be 2 bytes.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top