viewtopic.php?p=70457#p70457
> -- Александр Ильин писал(а):
> Внимание! Если на одной машине запущено два или более экземпляров ББ, то первый прерывается по Ctrl+Break, второй прерывается по Ctrl+Break, третий и последующие - не прерываются....На обсуждение указанного тормоза, который в линухах вообще не работает, наложилось утреннее зависание ББ (забыл INC в наскоро слепленном цикле) с последующем выискиванием и удалением нескольких временных файлов.Этим сподобился попробовать сделать файловый тормоз. Идея принадлежит ЕИЕ, он обещался сделать, но пока руки не дошли.Что получилось:

Наличие файла breakFileName проверяется каждые period секунд. По его появлении происходит попытка торможения, в случае успеха механизм отключается до удаления файла. (Факт удаления также проверяется каждые period секунд.)

Не проверенный момент: по идее, файл открывается из текущего каталога. Если в течении сеанса работы он изменится, то...

BB16rc6## Код:
```
PROCEDURE KeyboardWatcher (main: INTEGER): INTEGER;   (* runs in a thread *)
->      CONST period = 30 * 1000;
->      CONST breakFileName = "break.me";
      TYPE P = PROCEDURE(w: INTEGER): INTEGER;
      VAR res, a: INTEGER; top, h: WinApi.HANDLE; done: BOOLEAN;
         context: WinApi.CONTEXT; mod: Module; isHungAppWindow: P;
->         lastCheckTime, time: LONGINT; exist, stop:  BOOLEAN;
   BEGIN
      done := FALSE;
      isHungAppWindow := NIL;
      h := WinApi.LoadLibraryA("user32.dll");
      IF h # 0 THEN
         isHungAppWindow := S.VAL(P, WinApi.GetProcAddress(h, "IsHungAppWindow"))
      END;
->      lastCheckTime := Time(); stop := TRUE;
      LOOP
         res := WinApi.GetAsyncKeyState(WinApi.VK_CANCEL);
         ...
--->         time := Time();
         IF time - lastCheckTime >= period THEN
            lastCheckTime := time;
            exist := WinApi.GetFileAttributes(breakFileName) # -1;
            IF stop # exist THEN
            ELSIF ~stop (* & ~exist *) THEN
               stop := TRUE
            ELSE (* stop & exist *)
               res := WinApi.SuspendThread(main);
               context.ContextFlags := {0, 16};
               res := WinApi.GetThreadContext(main, context);
               mod := modList; a := context.Eip;
               WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO
                  mod := mod.next
               END;
               IF (mod # NIL) & (mod.name = "Kernel") THEN mod := NIL END;
               IF mod # NIL THEN
                  interrupted := TRUE;
                  INCL(S.VAL(SET, context.EFlags), 8);   (* set trap flag *)
                  res := WinApi.SetThreadContext(main, context);
                  stop := FALSE
               END;
               res := WinApi.ResumeThread(main);
               WinApi.Sleep(1);
               interrupted := FALSE
            END
--->         END
      END;
      RETURN 0
   END KeyboardWatcher;
```
