Seite 1 von 1

Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 00:27
von Sven
Ich brauche eine Überwachung, ob ein Programm noch läuft. Nichts Sicherheitskritisches, a la Virenscanner oder so. Es soll eine Art Diashow laufen, und wenn diese wegen eines Fehlers (kaputtes Bild, falsches Dateiformat, was auch immer) hängenbleibt oder abstürzt, soll sie beendet und neu gestartet werden.

Ich habe mir das so gedacht:

Programm startet => prüft ob WD läuft, wenn nein, wird WD gestartet
Programm sendet regelmäßig Kennung an WD
empfängt der WD keine Kennung, prüft er, ob das Programm noch vorhanden ist
=> wenn ja, schließen und neu starten, sonst nur neu starten
wird Programm regulär beendet, schließt es vorher den WD

Das Programm und der WD laufen auf einem Rechner. Wie kann ich die am besten kommunizieren lassen?

Virtuelle COM-Ports? Scheint mir sehr aufwendig, erfordert wahrscheinlich spezielle Treiber.
Lokale Netzverbindung? Scheint mir immer noch etwas aufwendig.
Über den Speicher? Geht das mit modernen Windosen noch, daß zwei Programme den gleichen Speicher verwenden? Wie könnte der WD erfahren, an welcher Speicherstelle er die Kennung findet. Die könnte man ja immer hochzählen.

Ich suche keine fertigen Programme, nur Brainstorming, wie man das effizient realisieren könnte.

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 01:57
von edel
Prg 1 öffnet ein unsichtbares Fenster, und setzt das handel des Fensters als Umgebungsvariable
Prg 1 startet Prg 2
Prg 2 holt sich die vererbte Umgebungsvariable, und sendet via SendMessage an das Fenster von Prg1 das WindowHandle.
Prg 1 Empfaengt WindowHandle und sendet per Timer eine Nachricht. kommt etwas zurueck, ist das Programm noch aktiv.

Beispiel :

Code: Alles auswählen

; Prg1

Enumeration #WM_USER
  #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE
  #REAGIERT_DIA_SHOW_WINDOW_NOCH
EndEnumeration

Global DIA_WINDOW = 0

Procedure StartDia()
  RunProgram("prg2.exe")
EndProcedure

Procedure Callback(hWnd, Msg, wParam, lParam)
  
  If Msg = #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE
    DIA_WINDOW = lParam    
  EndIf
  
  If Msg = #WM_TIMER
    If DIA_WINDOW
      If SendMessage_(DIA_WINDOW, #REAGIERT_DIA_SHOW_WINDOW_NOCH, 0, 0) = #True
        Debug "Lebt noch"
      Else
        Debug "Lebt nicht -> starte prg"
        StartDia()
        Delay(300)
      EndIf 
    Else
      StartDia()
    EndIf 
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure Main()
  
  Protected hWnd = 0
  
  hWnd = OpenWindow(0, 0, 0, 0, 0, "myMessageWindow", #PB_Window_Invisible)
  
  If hWnd 
    
    SetEnvironmentVariable("DIAMessageWindow", Str(hWnd))
    
    SetWindowCallback(@Callback())
    
    SetTimer_(hWnd, 0, 2000, #Null)
    
    Repeat
      WaitWindowEvent()
    ForEver
    
  EndIf
  
EndProcedure : End Main()

Code: Alles auswählen

; Prg2

Enumeration #WM_USER
  #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE
  #REAGIERT_DIA_SHOW_WINDOW_NOCH
EndEnumeration

Procedure Callback(hWnd, Msg, wParam, lParam)
  
  If Msg = #REAGIERT_DIA_SHOW_WINDOW_NOCH
    PrintN("message prg1")
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure Main()
  
  Protected hWnd = 0
  
  OpenConsole()
  
  OpenWindow(0, 0, 0, 100, 100, "DiaShow")
  SetWindowCallback(@Callback())
  
  hWnd = Val(GetEnvironmentVariable("DIAMessageWindow"))
  SendMessage_(hWnd, #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE, 0, WindowID(0))
   
  Repeat      
  Until #PB_Event_CloseWindow = WaitWindowEvent()   

EndProcedure : End Main()


Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 08:49
von Imhotheb
vielleicht lässt sich das auch mit thread(s) lösen?

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 10:10
von ts-soft
Imhotheb hat geschrieben:vielleicht lässt sich das auch mit thread(s) lösen?
Wenn das Programm abstürzt, ist normalerweise auch jeder Thread hinüber!
Sven hat geschrieben:Über den Speicher? Geht das mit modernen Windosen noch, daß zwei Programme den gleichen Speicher verwenden? Wie könnte der WD erfahren, an welcher Speicherstelle er die Kennung findet. Die könnte man ja immer hochzählen.
Vielleicht mit FileMap bzw. SharedMemory

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 21:18
von Sven
Hm, SendMessage habe ich auch schon überlegt, aber ich wollte so weit es geht mit PB-eigenen Funktionen arbeiten, um das Programm eventuell mal auf Linux übertragen zu können.

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 21:40
von edel
Dann kommen eigentlich nur noch die Netzwerkbefehle in Frage. Wobei über ReadProgramData muesste das auch gehen.

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 22:14
von freak
Wie wäre es mit einer einfachen Datei mit einem Zeitstempel drin?

Code: Alles auswählen

Global FileName$ = GetTemporaryDirectory() + "alive.txt"

Procedure ConfirmAlive()
  If CreateFile(0, FileName$, #PB_File_NoBuffering)
    WriteString(0, Str(Date()))
    CloseFile(0)
  EndIf
EndProcedure

OpenWindow(0, 100, 100, 300, 300, "Überwachtes Programm", #PB_Window_SystemMenu)
AddWindowTimer(0, 0, 1000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer
      ConfirmAlive()
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver

Code: Alles auswählen

Global FileName$ = GetTemporaryDirectory() + "alive.txt"

Procedure IsAlive()
  If ReadFile(0, FileName$)
    LastAlive = Val(ReadString(0))
    CloseFile(0)
    
    If Date() - LastAlive < 5
      ProcedureReturn #True
    EndIf        
  EndIf  
  
  ProcedureReturn #False
EndProcedure

OpenWindow(0, 500, 100, 300, 300, "Überwacher", #PB_Window_SystemMenu)
AddWindowTimer(0, 0, 1000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer
      If Not IsAlive()
        MessageRequester("", "Beendet!")
        End
      EndIf
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 22:24
von Sven
Ja, die RunProgramm-Funktionen sehen gut aus.

Dann werde ich das wohl umkehren:

WD starten, dieser startet das Programm, liest mit ReadProgramData() die Daten vom Programm, kommen eine Zeitlang keine Daten, wird das Programm "gekillt" und neu gestartet.

@freak: Kann das nicht Ärger geben, wenn ein Programm in eine Datei schreiben will, die ein anderes Programm gerade zum Lesen geöffnet hat?

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 16.06.2015 22:38
von freak
Sven hat geschrieben:@freak: Kann das nicht Ärger geben, wenn ein Programm in eine Datei schreiben will, die ein anderes Programm gerade zum Lesen geöffnet hat?
Das Öffnen geht dann einfach schief. Da aber die Datei immer nur sehr kurz offen ist sollte das in der Praxis kein Problem sein. Der Testcode liest/schreibt jeweils einmal pro Sekunde. Wenn du das in noch größeren Intervallen machst wird es in der Praxis kein Problem sein. Dafür ist die Lösung sehr einfach.

Jetzt wo ich drüber nachdenke kann man das Leseproblem leicht lösen: Das Testprogram öffnet die Datei einfach gar nicht sondern checkt nur mit GetFileDate() das Änderungsdatum der Datei. Dann ist es garantiert kein Problem.

Re: Watchdog für Programm - wie kommunizieren?

Verfasst: 01.07.2015 22:45
von Sven
Ich hab das jetzt über Network gelöst. Der Watchdog öffnet einen Server, startet das Programm mit RunProgram() und übergibt den Serverport per Programmparameter. Das Programm meldet sich als Client an und sendet eine regelmäßige Kennung für den Reset des Watchdog. Bleibt die Kennung aus, beendet der Watchdog das Programm mit KillProgram(), wartet eine Weile und startet es neu.

Funktioniert wunderbar für mehrere Clients gleichzeitig.

Mit Read/WriteProgrammData und den Konsolenbefehlen bin ich nicht klargekommen, auch störte mich die ständig geöffnete Konsole.