Problem mit Dienst beenden

Klassen, Objekte, Methoden, Instanzen

Moderator: Moderatoren

Antworten
Lars Vogelmann
Rookie
Rookie
Beiträge: 9
Registriert: Mi, 24. Okt 2012 10:29

Problem mit Dienst beenden

Beitrag von Lars Vogelmann »

Hallo,

ich habe ein Problem mit dem Beenden von einem Dienst. Ich habe eine xb2net-Anwendung, die als Dienst über ServiceApp installiert wurde. Installieren und starten klappt soweit. Wenn ich aber versuche, den Dienst zu beenden, bekomme ich immer die Fehlermeldung "Der Dienst konnte nicht beenden werden, Fehler 109: Pipe wurde beendet".

Ich habe mir mal ein Log eingebaut, die Anwendung wird korrekt beendet, läuft bis zum Quit durch. Nur der Servicecontroller macht ein Problem.

Ist übrigens meine erste Anwendung, die als Dienst laufen soll. Ich habe den Eindruck, als ob mir noch irgend etwas fehlt und deswegen der Dienst nicht sauber beendet wird.

Das Ganze findet auf einem Windows 2008 R2 Server statt, den gleichen Effekt habe ich auch unter Windows 7.

Hier mein Quellcode:

Code: Alles auswählen

oService := MyService()
oService:main := {||StartService()}
oService:stop := {||Terminate()}
oService:start()

CLASS MyService From ServiceApp
  EXPORTED:
    CLASS METHOD main
    CLASS METHOD stop
  HIDDEN:
    CLASS VAR lRunning
ENDCLASS

CLASS METHOD MyService:main()
  ::lRunning := .T.
  DO WHILE ::lRunning
      AppEvent(@mp1,@mp2)
  ENDDO
RETURN self

CLASS METHOD MyService:stop()
  ::lRunning := .F.
RETURN self


PROC Terminate( nPause )

    IF nPause == NIL
        nPause := 500
    ENDIF

   StartLog("Terminating HTTP server..." + CRLF + ;
            "Date: " + DTOC(DATE())      + CRLF + ;
            "Time: " + TIME())

   if soServer != NIL
      soServer:Stop()
      StartLog("HTTP server stopped"    + CRLF + ;
               "Date: " + DTOC(DATE())  + CRLF + ;
               "Time: " + TIME())

      soServer:onError := NIL
      soServer:Destroy() 
   endif

   if soSServer != NIL
      soSServer:Stop()
      StartLog("HTTPS server stopped"   + CRLF + ;
               "Date: " + DTOC(DATE())  + CRLF + ;
               "Time: " + TIME())

      soSServer:onError := NIL
      soSServer:Destroy()  
   endif

   // save all sessions
   // sessions can later be restored by using the /RESTORE command line parameter
   xbSession():SaveSessions()
   StartLog("HTTP server sessions saved" + CRLF + ;
            "Date: " + DTOC(DATE())      + CRLF + ;
            "Time: " + TIME())

   // close the log file
   if soTLog != NIL
      soTLog:Close()
   endif
   Sleep(nPause)
   StartLog("HTTP server terminated"  + CRLF + ;
            "Date: " + DTOC(DATE())  + CRLF + ;
            "Time: " + TIME())
   Quit
   Return

Grüße
Lars
Zuletzt geändert von brandelh am Mi, 06. Feb 2013 12:40, insgesamt 1-mal geändert.
Grund: Bitte das CODE Tag nutzen ! BRANDELH
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Problem mit Dienst beenden

Beitrag von Martin Altmann »

Moin,
Du solltest vielleicht Deine AppEvent ein wenig robuster nutzen:

Code: Alles auswählen

if ( nEvent := AppEvent( @mp1, @mp2, @oXbp, 1 ) ) <> xbe_None
	oXbp:handleEvent( nEvent, mp1, mp2 )
endif
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Problem mit Dienst beenden

Beitrag von brandelh »

ich würde den Code nicht so verschachteln ...

Code: Alles auswählen

nEvent := AppEvent( @mp1, @mp2, @oXbp, 1 ) 
if nEvent <> xbe_None
   oXbp:handleEvent( nEvent, mp1, mp2 )
endif
kann man leichter lesen ... und ich stell mir die Frage, ob ein Service überhaupt XbParts hat, die einen Event handeln müssen :?:

Ich habe keine Erfahrung mit Diensten aber als Event würde ich einen xbeP_Quit erwarten ...
wenn mehrere Threads im Spiel sind, müsste man die sauber beenden (sollte in der Doku zu Xb2NET stehen),
ansonsten ein QUIT ! oder Ende der Schleife

Code: Alles auswählen

[code]nEvent := AppEvent( @mp1, @mp2, @oXbp, 1 ) 
if nEvent = xbeP_Quit  // eventuell auch xbeP_Close zusätzlich
   quit // oder EXIT und danach das Programmende
elseif nEvent <> xbe_None
   oXbp:handleEvent( nEvent, mp1, mp2 )
endif
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Problem mit Dienst beenden

Beitrag von brandelh »

Hi,

ich habe mir gerade das Beispiel von der Hilfe angesehen und die Eventloop sieht der von LARS sehr ähnlich.

Code: Alles auswählen

// Implemetierung eines Dienstes 
// Das Beispiel demonstriert die wesentlichen 
// Schritte für die Implementierung eines Dienstes. 
// Der Dienst ruft alle 5 Sekunden lediglich die 
// Funktion Tone() auf, bis er den Stop Request empfängt. 
// Für die Installation dieses Dienstes wird auf das 
// Beispiel in der ServiceController() Klasse verwiesen. 

   #include "service.ch" 

   // Einstiegspunkt der ausführbaren Datei 

   PROCEDURE Main() 
      MyService():start() 
   RETURN 

   CLASS MyService From ServiceApp 
      EXPORTED: 
      CLASS METHOD main 
      CLASS METHOD stop 
      HIDDEN: 
      CLASS VAR lRunning 
   ENDCLASS  

   // Einstiegspunkt des Dienstes 
   CLASS METHOD MyService:main() 
      ::lRunning := .T. 
      DO WHILE ::lRunning 
         Tone( 400, 9 ) 
         Sleep( 500 ) 
      ENDDO 
   RETURN self 

   // Einstiegspunkt für Stop Request 
   CLASS METHOD MyService:stop() 
      ::lRunning := .F. 
   RETURN self 
Wenn die "Eventloop" so einfach aussehen darf, vermute ich dass dein Problem eher an zusätzlich laufenden Threads von XB2NET liegt als an der grundlegenden Funktion als Service.
Eventuell könnte folgende Änderung ein Ende erzwingen, aber am Besten wäre es sich bei Boris zu erkundigen,
was man ändern muss um einen XB2NET Server als Service zu betreiben ... wobei Martin das ja auch gemacht hat.

Code: Alles auswählen

   CLASS METHOD MyService:main() 
      ::lRunning := .T. 
      DO WHILE ::lRunning 
         Tone( 400, 9 ) 
         Sleep( 500 ) 
      ENDDO
      QUIT // WAS PASSIERT NUN ?
   RETURN self 
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Problem mit Dienst beenden

Beitrag von Martin Altmann »

Hubert,
eben - und Lars wartet mit seiner Eventschleife ewig (ohne Timeout) auf ein Event...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Problem mit Dienst beenden

Beitrag von brandelh »

Mir fallen noch zwei Sachen auf ...

Code: Alles auswählen

oService := MyService()
oService:main := {||StartService()}
oService:stop := {||Terminate()}
oService:start()
1. ohne Einbindung in eine Funktion / Prozedur, diese müssten also die automatische MAIN werden.
Hier werden 2 Funktionen den Codeblocks zugeordnet (die ich hier nicht finde) und unten sind die gleichnamigen Methoden definiert.
2. wenn ich mein Beispiel aufrufe wird die MAIN Prozedur zwar sauber abgearbeitet (LOG-datei wird erstellt), aber es wird kein Ton erzeugt bzw. Methoden aufgerufen ...
aber das ist ein anderes Thema ;-)
Gruß
Hubert
Lars Vogelmann
Rookie
Rookie
Beiträge: 9
Registriert: Mi, 24. Okt 2012 10:29

Re: Problem mit Dienst beenden

Beitrag von Lars Vogelmann »

Hallo Hubert,

das QUIT habe ich eingebaut, leider kein Effekt, immer noch derselbe Fehler beim Beenden des Dienstes.

Code: Alles auswählen

       CLASS METHOD MyService:main()
          ::lRunning := .T.
          DO WHILE ::lRunning
             Tone( 400, 9 )
             Sleep( 500 )
          ENDDO
          QUIT // WAS PASSIERT NUN ?
       RETURN self

Gruß
Lars
Zuletzt geändert von brandelh am Mi, 06. Feb 2013 15:29, insgesamt 1-mal geändert.
Grund: CODE Tags gesetzt, bitte selbst nutzen ;-)
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Problem mit Dienst beenden

Beitrag von brandelh »

Bitte die Quellcodes mit der Maus (oder Tastatur) markieren und dann den [ CODE ] Button oben drücken, dann wird der Quellcode gleich viel lesbarer ;-)

Beispiel:
for x = 1 to 200
if x = 100
if TestData()
machDies()
else
machJenes()
endif
endif
next
bei der Eingabe sah es noch gleich aus, aber der Browser ignoriert führende Blanks

Code: Alles auswählen

for x = 1 to 200
    if x = 100
       if TestData()
          machDies()
       else
          machJenes()
       endif
    endif
next
[ CODE ] und [ / CODE ] hingegen läßt den Text wie er ist und nutzt einen fixed font.
Man kann die natürlich auch ausschreiben (die Blanks dann weg lassen, die dienen nur der Ansicht hier) ...

Leider kann ich in der Sache nicht helfen.
Gruß
Hubert
Antworten