Avatar billede iakob Nybegynder
03. juni 2003 - 08:53 Der er 17 kommentarer og
2 løsninger

Kill af kørende Com Object lavet på MFC/Visual Studio 6.0

Jeg har et Com Object som bliver kaldt fra VS SQL Serveren.

Mit problem er at hvis der opstår en fejl kan mit objekt godt hænge og derfor returneres der aldrig noget til SQL. Jeg kan ikke lave en kill process via joblisten i Windows (adgang nægtet).

Eneste måde at terminere objektet på er at genstarte maskinen hvilket er dybt problematisk for mig.

Er der nogen som har en god idé til hvordan jeg kan ændre objektet så det kan slås ihjel eller så det selv terminerer, hvis det hænger?

Objektet er implementeret som en applikation, men bliver kørt som en service (dvs intet applikationsvindue)

Jeg kender ikke ret meget til thread og processstyring i C++. Og jeg vil gerne have en elegant og hurtig løsning på mit problem eller hjælp til at programmere løsningen (samtidigt med at jeg ikke kan udlevere koden). Derfor har jeg sat points lidt højt.
Avatar billede mufoxe Nybegynder
03. juni 2003 - 09:24 #1
Tag et kig på dette link. Der skulle gerne være det, du har brug for:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cossdk/htm/pgautomatingadmin_64fn.asp
Avatar billede mufoxe Nybegynder
03. juni 2003 - 09:25 #2
Ellers ville løsningen vel være at smide det i en try-catch blok (kommer meget an på hvad det er, der får objekter til at hænge).
Avatar billede killer_bee Nybegynder
03. juni 2003 - 10:42 #3
hvis du vil bare 'dræbe' processen kan du bruge

BOOL TerminateProcess(
  HANDLE hProcess, // handle to the process
  UINT uExitCode  // exit code for the process
);
Avatar billede soepro Nybegynder
03. juni 2003 - 11:04 #4
Normalt ligger der vel en eller anden form for loop-struktur i COM-objektet. Denne loop-struktur bør du tilføje en "udvej" i stil med:

// Globale variabler.
Thread      *thisPID;
bool        terminatePID;
bool        resetTIMER;
CKillThread* killThread;
:
:
// Opret "kill" tråden.
thisPID = handle; // Fra 'WinMain' eller hvad "main" proceduren nu hedder i COM-objectet.
resetTIMER = true;
killThread = CreateThread ...;
:
// Start COM hoved-loop
while (!terminatePID)
{
  // Vent på et indkommende request
  // req = getRequest
  resetTIMER = true;

  // Behandling af indkommende request
};

Du kan så udvide dit COM-object med en tråd (Thread) som du lader køre "ved siden af" sådan at den kan kill'en hovedtråden, hvis skidtet går dødt - f.eks. noget i stil med:

void CKillThread::Run(void)
{
  int waitCycle = 1800000; /* Vent 1800 sekunder, dvs. 1/2 time */
  while (resetTIMER) // Samme switch som i selve COM-tråden - den skal i princippet kodes "thread"-safe, men i denne sammenhæng betyder evt. manglende synkronisering kun at der går een "wait" cycle mere.
  {
    resetTIMER = false;
    Sleep(waitCycle);
  };

  // Kill hovedtråden.
  TerminateProcess(thisPID, 0);
} //
Avatar billede tam Nybegynder
03. juni 2003 - 11:51 #5
Normalt stopper et COM Object når dets RefCount er 0. Der er desværre ikke nogen måde at terminere et (normalt) COM Object med...

Men, når nu dit er implementeret som en service er det måske en mulighed alligevel...
Har du mulighed for at opdage, fra Objectet, at det hænger?
Hvis du kan det kan du prøve at stoppe servicen og starte den igen, og hvis du ikke kan det kan du slå den ihjel med TerminateProcess()
For at stoppe og starte servicen, fra servicen, kan du lave en batfil med følgende 2 linier

net stop dinservice
net start dinservice

og så kalde denne fil fra servicen, evt. med ShellExecute()...
Avatar billede tam Nybegynder
03. juni 2003 - 11:53 #6
soepro>

Øhhh, nej!
Der er ikke noget "MainLoop" eller andet i et COM Object, ligesom der heller ikke er i en normal dll.
Avatar billede segmose Nybegynder
03. juni 2003 - 11:54 #7
soepro - vil du ikke dræber dit COM object hvis der ikke kommer nogen request til COM hoved loopet, da du ikke får sat resetTIMER hvis der ikke er nogen request?
Avatar billede soepro Nybegynder
03. juni 2003 - 11:55 #8
tam >> Så COM-objectet aktiveres med et specifikt kald, som blot aldrig returnerer eller ? Kan Thread ideen ikke stadig bruges, hvis man kan sætte en maksimal "wait-time" på at COM-servicen skal returnere ?
Avatar billede soepro Nybegynder
03. juni 2003 - 11:57 #9
segmose >> Jo , det er lige nøjagtigt ideen. Hvis der ikke kommer et request inden for "waitCycle" tiden, så (ab-)ender COM-objektet.
Avatar billede segmose Nybegynder
03. juni 2003 - 12:01 #10
soepro - jeg troede iden var at skyde den hvis den hang, ie. ikke svarede og ikke hvis den ikke fik request.
Avatar billede tam Nybegynder
03. juni 2003 - 12:01 #11
soepro >> Jo, man kan vel stadig implementere din ide med et extra thread der "holder øje" med at det ikke timer ud...

Og ja, COM Objecter holder ikke sig selv i live med et loop eller noget, det er kun sålænge at de funktioner der bliver kaldt de kører...
Avatar billede iakob Nybegynder
03. juni 2003 - 12:26 #12
Jeg er lidt ked af at sige det, men mit objekt kører ikke som en service i NT-sammenhæng. Det jeg mente med det (I må undskylde min knudrede terminologi) var blot at der var ikke noget vindue med menuer på eller noget.

Når applikationen hænger kan det være fordi der er en dialog-boks (jeg har ikke styr over al koden selv pga kodegenbrug). Dialogen kommer ikke frem på skærmen men applikationen venter alligevel på et OK eller CANCEL.

En anden mulighed kan være at dens kald til en database hænger eller en helt tredie og ukendt mulighed ;-)
Avatar billede soepro Nybegynder
03. juni 2003 - 12:30 #13
segmose >> Forskellen på de to (altså hænge <> ikke modtage noget) bliver svær at fange, sådan som jeg ser det. En løsning må så være kun starte 'killer' tråden, såfremt man er i gang med at behandle et request:

comObject::Method(void)
{
  killThread.ResetTimer(); // Hvis dette ikke kan "overloades" ind i trådens 'OnResume' event. (Kan man i C++ Builder's TThread.)
  killThread.Resume();

  // Process request
  doSomething();

  // Done - suspend killer thread.
  killThread.Suspend();
}
Avatar billede soepro Nybegynder
03. juni 2003 - 12:32 #14
Ovenstående bevirker selvfølgelig er der er en maksimal tid COM-objektet må (kan) bruge på at behandle et request - hvis den ikke er færdig inden waitCycle er nået, så slår COM-objektet siig selv ihjel.
Avatar billede segmose Nybegynder
03. juni 2003 - 12:43 #15
Soepro - ja, det kom jeg også i tanke om sådan ca. 2 sekunder efter jeg fik trykket udfør :) det er jo en simple timer overvågning.

Hvis det skulle laves mange gang ville jeg dog lave sådan noget i tilgift til din CKillThread::Run

class KillThread {
public:
  KillThread(long waitCycle = 1800000) {
    killThread = CreateThread ...; // eller ResetTimer/Resume
  }
  ~KillThread() {
    ... // stop killThread eller Suspend
  }
}



comObject::Method(void) {
  KillThread
    waitForTimeOut(); // ville nok i de fleste tilfælde være fx. KillThread TO(117);

  // Process request
  doSomething();
}

forenkeler sagerne og jeg ville ikke glemme alle reset/resume/suspend.
Avatar billede soepro Nybegynder
03. juni 2003 - 13:29 #16
segmose >> Udnytte constructoren og de-constructoren samt "out of scope" delete - OK det er smartere !

Din metode betyder vel at hver metode har sin egen "killer" thread - betyder det ikke at det første request der "time-outer" killer alle igangværende requests ? Eller bliver de enkelte requests/metode kald rent faktisk behandlet under hver sin PID ?
Avatar billede segmose Nybegynder
04. juni 2003 - 09:24 #17
"segmose >> Udnytte constructoren og de-constructoren samt "out of scope" delete - OK det er smartere ! "
Ja, jeg synes også at Bjarne er meget smart :)

Det kommer jo an på hvordan man ønsker det, hvis der er flere forskellige processer der kalder COM-objectet samtidig (har de så forskellig pid? jeg ved det ikke da jeg ikke har nogen erfaring med COM) skal man nok overveje nøje om man vil skyde alle igangværende (metode 1) hvis en får timeout.
Hvilket også var grunden til at jeg tilføjede ResetTimer/Resume/Suspend (metode 2) til (de-)constructor, hvor alt efter brug jeg så skulle vælge den rigtig metode.

Der er jo altid problemer/udfordringer med:
- threaded
Kan vi skyde på thread niveau eller kun på process niveau?
- reentrant
Metode 2: hvis man har en fælles timeout kan man få det tilfælde at en process hænger men der hele tiden kommer nye så timeren bliver reset hele tiden og man derfor ikke vil få løst problemet, så skulle jeg udvide kill med en anden timeout der checker om der findes et tidspunkt hvor kun en process kører (den der hænger) før jeg skyder objectet, og ellers skyder alle alligevel efter en tid hvis der aldrig er mindre end 2 processer.
- deadlock
ud over at selve COM-objectet skal undgå deadlocks, skal CKillThread/KillThread også.
Avatar billede segmose Nybegynder
04. juni 2003 - 09:24 #18
Og det skulle så have været et svar.
Avatar billede iakob Nybegynder
11. juni 2003 - 08:49 #19
Tak for svarene og undskyld jeg var så lang tid om at give points. Jeg har ikke været på arbejde :-)

I må deles om points fordi så vidt jeg kan se så hjalp I hinanden til at give det endelige råd.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester