1

I have a generic windows build batch (i.e. build.bat) that is running in parrallel with different parameters.

start build.bat device1
start build.bat device2
start build.bat device3

But in that batch there is an executable that crashes when it gets called in parrallel.

Is it possible, with windows build-in functions, to block this call when it is already running in another batch and continue when it has finished in that other batch?

Let's say the content of that batch is

start delay 5

When the batch gets called several times then the delay must not run when another delay is currently running.

This is similiar to semaphores.

So the goal is to have something like this

CheckAndWaitIfDelayIsRunning
start delay 5

Thanks in advance.

Martin S
  • 377
  • 3
  • 14
  • @AdrianoRepetti: The `start` command does NOT have any option that wait for the termination _of another process_... – Aacini Aug 12 '16 at 15:36
  • @Aacini true, I just re-read the question and I missed the main point (wait for another process, not 2nd batch itself to terminate) – Adriano Repetti Aug 15 '16 at 09:32

2 Answers2

6

You can build semaphores in batch by using a lock by file.

:lock
2>nul (
  > sema1.lock (
    delay 5
    REM The next line is for proper finishing the lock block
    (call )
  )
) || goto :lock

The trick is, that writing to sema1.lock is only allowed for one process at time.
Any other process will fail and skip the inner block, the || goto :lock will retry until it's possible to write to the sema1.lock file.
One drawback for this technic is the consuming of CPU, as this semaphore not really wait, it's more of a polling semaphore.

For more see SO:How do you have shared log files under Windows?

Community
  • 1
  • 1
jeb
  • 78,592
  • 17
  • 171
  • 225
  • How about inserting a `timeout 1` command to reduce polling rate? would that work? – aschipfl Aug 12 '16 at 09:53
  • 1
    Yes, that works, but can slow down the program reaction, as semaLock will wait 0.5seconds in the average, when waiting for a release from another thread – jeb Aug 12 '16 at 09:56
2

According to the answer I optimized two things:

  • Console output is still visible and not redirected into a file
  • %errorlevel% contains the error from my task

It uses a folder as lock that gets created the first time.
Ping is used as waiting time and set to 1000 ms.
It counts the number of cycles the thread waits till it gets the permission to excecute its task.

Script

set lockMyName="%TEMP%\my.lock"    
set lockMyCounterMs=0
set lockMyTimeMs=1000
@echo  [ INFO ] Getting my lock...
:lock_my
md %lockMyName% 2>nul
if "%errorlevel%" neq "0" (
    set /a lockMyCounterMs+=%lockMyTimeMs%
    :: commonly used timeout without waiting for input (must be invalid ip address)
    ping 1.0.0.0 -n 1 -w %lockMyTimeMs% >nul
    goto :lock_my
)
@echo  [ INFO ] ... locked ^(waited %lockMyCounterMs% ms for lock^)

 ::do your task here

@echo  [ INFO ] ...release my lock
rd /Q %lockMyName% 2>nul
Martin S
  • 377
  • 3
  • 14