Seite 1 von 1

Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 11:44
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

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 12:20
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

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 12:43
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

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 13:03
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 

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 13:58
von Martin Altmann
Hubert,
eben - und Lars wartet mit seiner Eventschleife ewig (ohne Timeout) auf ein Event...

Viele Grüße,
Martin

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 14:14
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 ;-)

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 14:44
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

Re: Problem mit Dienst beenden

Verfasst: Mi, 06. Feb 2013 15:24
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.