Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29234 Discussions

Help needed to check whether another program is running

DavidWhite
Valued Contributor II
2,415 Views

Does anyone have an example of how to check whether another program is running from within Fortran?

I think the WinAPI function is GetProcesses, but can't find anything else.

What I'm trying to do is to run multiple copies of a program by creating a commnad file which uses the START command, execute it using SYSTEMQQ, and then once all copies have completed, collate all the results.

Thanks,

David

 

0 Kudos
13 Replies
IanH
Honored Contributor III
2,415 Views

If you can use the Windows API and your Fortran program directly launches the other programs it is easy enough - you can wait on the process handles returned from a series of CreateProcess calls using WaitForMultipleObjects.  This is much more simple and robust than querying the list of active processes (see here for a C example) and relying on that.

If you were back at a design stage for this the you could perhaps map each child process across to a Fortran image, and use coarrays.  I imagine that might be a bit tricky to retrofit though.

0 Kudos
Steven_L_Intel1
Employee
2,415 Views

You can use the Process Status API (module PSAPI) to do this. Look at the ProcessStatus sample we provide. This one gets memory usage for each process, but you can use GetProcessImageFileName to get the executable file name instead.

0 Kudos
DavidWhite
Valued Contributor II
2,415 Views

Steve,

For some reason, the ProcessStatus example does not list any of my running Fortran programs. But if I lookup the PID using TaskManager and put that into my adapted version of ProcessStatus, it correctly returns the file name.  Why doesn't the process list in the example get all of the running process PID's?

Thanks,

David

0 Kudos
Steven_L_Intel1
Employee
2,415 Views

Interesting - when I try the sample it does show a Fortran program I have run separately. Please attach your modified version and I'll try it out.

I've attached my version. Instead of GetProcessImageFIleName, which returns the filename in \device\... format, I used QueryFullProcessImageName (available in Vista and later.) This isn't in module KERNEL32 so I declared it independently.

0 Kudos
DavidWhite
Valued Contributor II
2,415 Views

Here is my version.

It appears that when I call my program from inside ProcessStatus, then the processID cannot be obtained. If my program is still running (e.g. from a previous execution of ProcessStatus), then it detects the processID.  I thought at first that checking the ProcessID's was happening so fast that they were all checked before the other program could start, but this is definitely not the problem.

I have tried running this both from within VS and directly from Windows Explorer, with the same results.

Thanks

David

0 Kudos
IanH
Honored Contributor III
2,415 Views

Perhaps I have misunderstood your intent - but it appears that you get the list of running processes (via EnumProcesses) before you have created your process of interest (via SYSTEMQQ).

0 Kudos
DavidWhite
Valued Contributor II
2,415 Views

Thanks, Ian.  I guess if the logic is wrong, the program won't work! :-(

David

0 Kudos
IanH
Honored Contributor III
2,415 Views

In the absence of mitigating reasons to the contrary, I still think you'd be far better off directly managing the processes yourself, rather than this indirect approach of watching the filename.

The attached was something I put together a while ago when fooling around looking at options around tracking child process success (I can't remember what the background was).  Most of it is not relevant here - but if you have a look at the check_return_code internal procedure you'll see a call to CreateProcess and WaitForSingleObject.  Pop the CreateProcess in a loop, make the relevant arguments arrays, and change the Wait API to WaitForMultipleObjects, and you're done.  Scalable (wait for thousands of kids if you want), robust, CPU friendly (no polling)...

(Is the issue the use of an intermediate batch file to launch the child jobs?)

0 Kudos
DavidWhite
Valued Contributor II
2,415 Views

Thanks, Ian.  I'll look at it tomorrow.

I looked at using the batch file to run the child jobs becuase the START command enables me to sequentially start multiple copies which will run concurrently.

I started looking at parallelizing my program, but due to the data arrangement it appears that this would be a major undertaking, not just in restructuring how the program works, but in testing.  As a major use of the program involves running mutliple independent cases, the next best solution would be to run multiple copies of the program (albeit with memory and load time implications). Hence the solution I am looking at.

You suggest launching the program using create process - can this include command line arguments, because if I am to do this without any rewriting my application, I would need to be able to specify some, particularly the input file name.

Thanks,

David

0 Kudos
IanH
Honored Contributor III
2,415 Views

Yep - it allows a command line (it has to - it, or its siblings, are the relatively low level API's that any Win32 process gets created through).  You may need to quote parts of the command line if it contains things that might confuse the language runtime for the child process when it goes about splitting that command line up into individual arguments.  Depending on how you specify the program to be executed, you may also need to quote that if its path or name contains spaces.  An example of the logic that I think (which is materially different to "I know"!) is required for the command line (in particular) is in main_worker, see the msdn page for CreateProcess for more info.

What CreateProcess won't do on its own is things like command line redirection (program.exe > output.txt), or execution of programs that are not exe's (e.g. it won't execute batch files or other scripts).  A simple workaround for that is to use cmd.exe with appropriate command line arguments as an intermediate child process.

(Not relevant to your use case, but what I attached up thread has silliness in the check_event internal procedure with remnant crap in the  assignment to success_flag.)

0 Kudos
DavidWhite
Valued Contributor II
2,415 Views

Ian,

How do I define the proc_info variable as an array and then get it to work with WaitforMultipleObjects?

I used

TYPE (T_PROCESS_INFORMATION),DIMENSION(nCount) :: proc_info

and

proc_info(iarg) as the argument in the CreateProcess call, but

wait_result = WaitForMultipleObjects(nCount, proc_info%hProcess, TRUE, INFINITE)

gets me stumped.

How do I pass the whole array of pointers to WaitForMultipleObjects?

As shown above, I get a compile error:

Error 1  error #6634: The shape matching rules of actual arguments and dummy arguments have been violated.   [HPROCESS] C:\Open\kwc54dw\Dev\Multiloader\multiloader.f90 108

Thanks,

David

0 Kudos
andrew_4619
Honored Contributor III
2,415 Views

I think  WaitForMultipleObjects wants a single pointer (address) for a contiguous array of handles. I think (I am not certain) you need to create an array in type Integer(handle) e.g. Integer(handle) :: fred(ncount) and then asign fred= proc_info%hProcess and then pass loc(fred)

0 Kudos
IanH
Honored Contributor III
2,415 Views

app4619 has it.  Simple example attached.

It is a shame that the IFWIN interface wasn't (also) declared to take an assumed size integer array.

(I see I lied a bit about the thousands of child processes too - the limit is 64 and then you have to start playing games waiting on child threads that are waiting on objects.)

0 Kudos
Reply