Re: [Mingw-w64-public] issues with application to run commands in parallel on Windows

2019-05-06 Thread Vincent Torri
On Tue, May 7, 2019 at 12:17 AM David Mathog  wrote:
>
> On 04-May-2019 20:31, Liu Hao wrote:
> > 在 2019/5/4 上午6:16, David Mathog 写道:
>
> Thanks for the feedback, but I'm still nowhere near getting this to
> work.
>
> >>
> >> Issues:
> >>
> >>
> >> 1.  Compiler warnings:
> >>
> >> c_spawn_n.c: In function 'main':
> >> c_spawn_n.c:47:13: warning: passing argument 3 of 'CreateThread' from
> >> incompatible pointer type [-Wincompatible-pointer-types]
> >>  RunCommand, // thread function name
> >>  ^~
> >
> > `LPTHREAD_START_ROUTINE` is the type of the parameter of
> > `CreateThread()`, which a pointer-to-function. The proper return type
> > for a thread procedure is `DWORD` rather than this thing.
>
> Changed the called routine to (see below):
>
> DWORD  RunCommand(  void *lpParam  ){

try :

DWORD WINAPI Runcommand(LPVOID lpParam) { ...}

see https://docs.microsoft.com/en-us/windows/desktop/procthread/creating-threads

Vincent Torri


___
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public


Re: [Mingw-w64-public] issues with application to run commands in parallel on Windows

2019-05-06 Thread Liu Hao
在 2019/5/7 上午6:17, David Mathog 写道:
> Changed the called routine to (see below):
> 
> DWORD  RunCommand(  void *lpParam  ){
> 

Insert an `__stdcall` before `RunCommand`. The calling convention is
part of the function type.

>>
>>> 2.  when run procs is shown as -1, not sure how that happens.
>>
>> Use `WaitForSingleObject()` to await **every** thread in a loop. Do not
>> use `WaitForMultipleObjects()` as it has a upper limit of number of
>> handles to wait for, and the return value is hard to handle properly (as
>> you already did that wrong).
> 
> You lost me. WaitForSingleObject() will only wait on a single handle at
> a time.  There might
> be 20 subprocesses running, each with its own handle.  A function is
> needed which will return
> when the first of those exits.  Would that not be
> WaitForMultipleObjects()?   Even if it will
> only work for lets say the first 16 processes, hopefully once those exit
> the invisible ones
> would slide into view?  Or maybe it doesn't work that way?
> 

If a thread terminates then its state becomes signaled; if you wait for
it a second time then the wait function returns immediately stating that
it is signaled.

To mimic the POSIX `wait()` or `pthread_join()` behavior, for each
signaled thread, you have to close its handle and remove it from the
wait list for the next `WaitForMultipleObjects()` call.

If I were you I would just write a loop that awaits ALL threads for
100ms. When the wait function returns, data can be copied from pipes to
the standard output. The loop terminates only when all threads exit,
whose handles are closed after the loop.


-- 
Best regards,
LH_Mouse



signature.asc
Description: OpenPGP digital signature
___
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public


Re: [Mingw-w64-public] issues with application to run commands in parallel on Windows

2019-05-06 Thread David Mathog

On 04-May-2019 20:31, Liu Hao wrote:

在 2019/5/4 上午6:16, David Mathog 写道:


Thanks for the feedback, but I'm still nowhere near getting this to 
work.




Issues:


1.  Compiler warnings:

c_spawn_n.c: In function 'main':
c_spawn_n.c:47:13: warning: passing argument 3 of 'CreateThread' from
incompatible pointer type [-Wincompatible-pointer-types]
 RunCommand, // thread function name
 ^~


`LPTHREAD_START_ROUTINE` is the type of the parameter of
`CreateThread()`, which a pointer-to-function. The proper return type
for a thread procedure is `DWORD` rather than this thing.


Changed the called routine to (see below):

DWORD  RunCommand(  void *lpParam  ){

but ...

gcc -g -O0 -o c_spawn_n c_spawn_n.c
c_spawn_n.c: In function 'main':
c_spawn_n.c:47:13: warning: passing argument 3 of 'CreateThread' from 
incompatible pointer type [-Wincompatible-pointer-types]

 RunCommand, // thread function name
 ^~
In file included from 
C:/progs/msys32/mingw32/i686-w64-mingw32/include/winbase.h:29:0,
 from 
C:/progs/msys32/mingw32/i686-w64-mingw32/include/windows.h:70,

 from c_spawn_n.c:7:
C:/progs/msys32/mingw32/i686-w64-mingw32/include/processthreadsapi.h:163:28: 
note: expected 'LPTHREAD_START_ROUTINE' but argument is of type 'DWORD 
(*)(void *) {aka long unsigned int (*)(void *)}'
   WINBASEAPI HANDLE WINAPI CreateThread (LPSECURITY_ATTRIBUTES 
lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE 
lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD 
lpThreadId);

^~~~
The processthreadsapi.h header line does indeed contain the type which 
the compiler

is warning about:

grep CreateThread 
C:/progs/msys32/mingw32/i686-w64-mingw32/include/processthreadsapi.h


  WINBASEAPI HANDLE WINAPI CreateThread (LPSECURITY_ATTRIBUTES 
lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE 
lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD 
lpThreadId);


I don't see how to reconcile this.




2.  when run procs is shown as -1, not sure how that happens.


Use `WaitForSingleObject()` to await **every** thread in a loop. Do not
use `WaitForMultipleObjects()` as it has a upper limit of number of
handles to wait for, and the return value is hard to handle properly 
(as

you already did that wrong).


You lost me. WaitForSingleObject() will only wait on a single handle at 
a time.  There might
be 20 subprocesses running, each with its own handle.  A function is 
needed which will return
when the first of those exits.  Would that not be 
WaitForMultipleObjects()?   Even if it will
only work for lets say the first 16 processes, hopefully once those exit 
the invisible ones

would slide into view?  Or maybe it doesn't work that way?



Don't forget to `CloseHandle()` when a thread handle is out of 
interest.

The POSIX function `wait()` waits for a child process and frees its
resource, but on Windows you close its handle explicitly; wait 
functions

do not free resources of it.


OK, added that.  For good measure set the handle pointer to NULL after 
closing it.





3.  cannot tell very well if this is actually starting multiple
processes or if it
is just running sequentially.
4.  there are now about about 100 cmd.exe processes showing up in
Windows Task Manager.


The `system` function passes its argument to the program designated by
the environment variable `COMSPEC` (which seems to have to be an
absolute path), which by default is `CMD.EXE` so you get a number of
instances.

If this is unacceptable you have to spawn child processes using
`CreateProcess()` and redirect standard streams yourself. There is a
nice document about this [1].

[1]
https://docs.microsoft.com/en-us/windows/desktop/ProcThread/creating-a-child-process-with-redirected-input-and-output


So something is hanging somewhere.  It was run both in  "MSYS2 Mingw 
32"

and a W7
cmd shell.   These processes are not visible in "ps -ef" in the 
former.


`ps` only shows programs that run on the abstraction layer for POSIX of
MSYS2; native programs are out of its management.

5.  Pretty sure I'm not checking status right on the thread creation 
and

not
passing the system() exit status back correctly (or at all).
6.  During the test it says this a variable number of times:

  The process cannot access the file because it is being used by 
another

process.


Rewrote the example.  The input file was simplified to commands3.txt and 
is now:


dir #c_spawn_n.c# > #c_spawn_n.c#.killme
dir accudate.1 > accudate.1.killme
dir accudate.c > accudate.c.killme

(which should run in either shell, those were just 3 files which were 
available

in the current directory.)

Rewrote the code to NOT check for running processes until all (3) were 
started.

Ran it like:

 ./c_spawn_n DEBUG firstempty 0 command >dir #c_spawn_n.c# > #c_spawn_n.c#.killme< 
len 40 procs 0
DEBUG firstempty 1 comman

Re: [Mingw-w64-public] issues with application to run commands in parallel on Windows

2019-05-04 Thread Liu Hao
在 2019/5/4 上午6:16, David Mathog 写道:
> 
> Issues:
> 
> 
> 1.  Compiler warnings:
> 
> c_spawn_n.c: In function 'main':
> c_spawn_n.c:47:13: warning: passing argument 3 of 'CreateThread' from
> incompatible pointer type [-Wincompatible-pointer-types]
>  RunCommand, // thread function name
>  ^~

`LPTHREAD_START_ROUTINE` is the type of the parameter of
`CreateThread()`, which a pointer-to-function. The proper return type
for a thread procedure is `DWORD` rather than this thing.

> 2.  when run procs is shown as -1, not sure how that happens.

Use `WaitForSingleObject()` to await **every** thread in a loop. Do not
use `WaitForMultipleObjects()` as it has a upper limit of number of
handles to wait for, and the return value is hard to handle properly (as
you already did that wrong).

Don't forget to `CloseHandle()` when a thread handle is out of interest.
The POSIX function `wait()` waits for a child process and frees its
resource, but on Windows you close its handle explicitly; wait functions
do not free resources of it.

> 3.  cannot tell very well if this is actually starting multiple
> processes or if it
> is just running sequentially.
> 4.  there are now about about 100 cmd.exe processes showing up in
> Windows Task Manager.

The `system` function passes its argument to the program designated by
the environment variable `COMSPEC` (which seems to have to be an
absolute path), which by default is `CMD.EXE` so you get a number of
instances.

If this is unacceptable you have to spawn child processes using
`CreateProcess()` and redirect standard streams yourself. There is a
nice document about this [1].

[1]
https://docs.microsoft.com/en-us/windows/desktop/ProcThread/creating-a-child-process-with-redirected-input-and-output


> So something is hanging somewhere.  It was run both in  "MSYS2 Mingw 32"
> and a W7
> cmd shell.   These processes are not visible in "ps -ef" in the former.

`ps` only shows programs that run on the abstraction layer for POSIX of
MSYS2; native programs are out of its management.

> 5.  Pretty sure I'm not checking status right on the thread creation and
> not
> passing the system() exit status back correctly (or at all).
> 6.  During the test it says this a variable number of times:
> 
>   The process cannot access the file because it is being used by another
> process.

It is mostly due to the fact that the same file is opened and closed
repeatedly and individually by each child CMD.EXE. So you probably have
to take the `CreateProcess()` approach and do your own redirection,
buffering, etc.

> 
> I think that means that it has problems with >>test_out.log running on
> multiple processes
> at once and that there is some implicit file locking.
> 


-- 
Best regards,
LH_Mouse

-- 
Best regards,
ltpmouse



signature.asc
Description: OpenPGP digital signature
___
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public


[Mingw-w64-public] issues with application to run commands in parallel on Windows

2019-05-03 Thread David Mathog

Hi all,

I maintain a little package with some text and binary utilities here:

  https://sourceforge.net/projects/drmtools/

In the last release the "execinput" program was modified so that instead 
of running
just one command it could run N at a time.   Like so (silly example to 
calculate
md5sum values for every file in a directory and store each in an ".md5" 
file, using

20 parallel processes):

ls -1 | extract -fmt 'md5sum [1,] > [1,].md5 ' | execinput -t 20

This uses fork() and wait() and works fine on linux.

Problem is, on windows there is not a strict equivalent for those 
functions.
Below is a first pass at getting something similar to work.  It just 
reads from stdin
and tries to create a thread in which it does a system() call.  At the 
moment it has several
issues, none of which I understand very well.  Compiled in 32 bit 
Mingw64 on a Windows 7 32 bit system (if that is the right way to say 
that) with:

  gcc -g -O0 -o c_spawn_n c_spawn_n.c
Not sure what release of Mingw64 this is but it was installed circa 
8/29/2018.


For the tests described below it was given the task of "DIR onefile can 
concatanate result to a single file", like so:


 ls -1  | extract -fmt 'dir [1,] >> test_out.log' >many_dir.txt
 head -3 many_dir.txt
dir #c_spawn_n.c# >> test_out.log
dir accudate.1 >> test_out.log
dir accudate.c >> test_out.log
./c_spawn_n oops3.txt
#preceding was msys, for cmd.exe without the leading path

Issues:


1.  Compiler warnings:

c_spawn_n.c: In function 'main':
c_spawn_n.c:47:13: warning: passing argument 3 of 'CreateThread' from 
incompatible pointer type [-Wincompatible-pointer-types]

 RunCommand, // thread function name
 ^~
In file included from 
C:/progs/msys32/mingw32/i686-w64-mingw32/include/winbase.h:29:0,
 from 
C:/progs/msys32/mingw32/i686-w64-mingw32/include/windows.h:70,

 from c_spawn_n.c:7:
C:/progs/msys32/mingw32/i686-w64-mingw32/include/processthreadsapi.h:163:28: 
note: expected 'LPTHREAD_START_ROUTINE' but argument is of type 'DWORD 
(__attribute__((__stdcall__)) * (*)(void *))(void *)'
   WINBASEAPI HANDLE WINAPI CreateThread (LPSECURITY_ATTRIBUTES 
lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE 
lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD 
lpThreadId);

^~~~
c_spawn_n.c: In function 'RunCommand':
c_spawn_n.c:70:12: warning: return makes pointer from integer without a 
cast [-Wint-conversion]

 return (retval);
^
2.  when run procs is shown as -1, not sure how that happens.
3.  cannot tell very well if this is actually starting multiple 
processes or if it

is just running sequentially.
4.  there are now about about 100 cmd.exe processes showing up in 
Windows Task Manager.
So something is hanging somewhere.  It was run both in  "MSYS2 Mingw 32" 
and a W7

cmd shell.   These processes are not visible in "ps -ef" in the former.
5.  Pretty sure I'm not checking status right on the thread creation and 
not

passing the system() exit status back correctly (or at all).
6.  During the test it says this a variable number of times:

  The process cannot access the file because it is being used by another 
process.


I think that means that it has problems with >>test_out.log running on 
multiple processes

at once and that there is some implicit file locking.


Here is the small test program's code:


// c_spawn_n.c
// TEST program to run up to 20 commands in parallel as subprocesses.
// Read commands from stdin.
//
//

#include 
#include 
#include 
#include 
#include 
#include 

// prototypes
LPTHREAD_START_ROUTINE RunCommand( LPVOID lpParam ); // runs thread

int max_threads=20;
int procs=0;// Number of processes running

int main(int argc, char *argv[]){
#define MAXSTRING 256
   char *command = malloc(MAXSTRING);
   char **ThrCommands = calloc(sizeof(char *), max_threads);
   HANDLE *ThrHandles = (HANDLE *) calloc(sizeof(HANDLE),max_threads);
   DWORD  *ThreadIds = (DWORD *) calloc(sizeof(DWORD),max_threads);
   int   firstempty=0;
   int   procs=0;
   DWORD retVal;
   while(1){
if(NULL == fgets(command,MAXSTRING,stdin))break;

if(procs){
firstempty = WaitForMultipleObjects(
 max_threads, ThrHandles, FALSE, INFINITE);
procs--;
GetExitCodeThread(ThrHandles[firstempty], &retVal);
fprintf(stderr,"DEBUG thread %d exited with status %ul\n",
firstempty,retVal);
}

fprintf(stderr,"DEBUG firstempty %d command >%s< len %d\n",
firstempty,command,strlen(command));
ThrCommands[firstempty] = strdup(command); // save it
ThrHandles[firstempty] = CreateThread(
NULL,   // default security attributes
0,  // use default stack size
RunCommand, // thread function name
ThrCommands[firstempty],// argument to th