Joakim Stien
Joakim Stien

Reputation: 45

Execution abnormalities depending on process creation (ShellExecute vs CreateProcess)

We're running a Windows Service which is responsible for monitoring a set of processes. The service is basically just responsible for (a) checking if the defined jobs are running, and (b) starting the jobs if they are not.

The service is created via the following command (sc: https://technet.microsoft.com/en-us/library/bb490995.aspx):

sc create "My Service" binPath= C:\heyoo\myservice.exe type= own start= auto error= normal
sc start "SCF Service"

One of the jobs the service is responsible for creating is 'Camera.exe'. Camera.exe retrieves a video feed from the connected cameras (FireWire 1394), and does some processing on them.

A week ago, the service was rewritten from using ShellExecute to use CreateProcess so it is able to better monitor the defined jobs (as it gets the HANDLE to the process).

ShellExecute call (old method):

bool Execute()
{
    int result = (int)ShellExecute(NULL, "open", "C:\\bin\\Camera.exe", NULL, NULL, SW_SHOWDEFAULT);
    return result > 32;
}

CreateProcess call (new method):

// Called with Execute("C:\\bin\\Camera.exe", "");
bool Execute(std::string prog, std::string args)
{
    std::string cmd = std::string(prog) + " " + args;
    char *path = new char[cmd.length()+1];
    strcpy(path, cmd.c_str());

    STARTUPINFO si = {0};
    si.cb = sizeof(STARTUPINFO);
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

    DWORD creationFlags = REALTIME_PRIORITY_CLASS;

    BOOL result = CreateProcess(NULL, path, NULL, NULL, FALSE, creationFlags, NULL, NULL, &si, &pi);
    delete[] path;

    if (result) {
        SetProcInfo(pi);
    }

    return result;
}

With the new CreateProcess method, we noticed that (A) the network systematically fails after a certain interval, and (B) the images retrieved from the cameras contain invalid timestamps (correct timestamps are crucial to us).

A frequently takes down the entire network connection, and requires a reboot to get back online. B causes the processing of images to fail, as we are highly dependent on valid timestamps.

The problems (A & B) does only arise when Service.exe is run as a service. When running Service.exe or Camera.exe from the command line, none of the problems occurr.

Today I removed the CreateProcess calls from the service (went back to ShellExecute), and the problems disappeared again. What am I doing wrong with the API call?

Upvotes: 1

Views: 511

Answers (1)

David Heffernan
David Heffernan

Reputation: 612794

DWORD creationFlags = REALTIME_PRIORITY_CLASS;

This is the most obvious difference. When you call ShellExecute, the process will be created with normal priority. The documentation for real time priority says:

Process that has the highest possible priority. The threads of a real-time priority class process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.

You really don't want to do this!

Pass 0 as the creation flags. The documentation says:

If none of the priority class flags is specified, the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority class of the creating process is IDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.

For what it is worth, you can obtain a process handle by using ShellExecuteEx rather than ShellExecute. In fact you should always prefer ShellExecuteEx to ShellExecute since the latter cannot report errors properly. Even so, you are creating a new process, and so CreateProcess is the right function for that task.

Upvotes: 3

Related Questions