[DUG] Program crashes - anyone knows why?

Gajo Csaba csaba at enyem.com
Mon Nov 27 11:35:18 NZDT 2006


On Sun, 26 Nov 2006 23:16:50 +0100, Matthew Comb <matt at ferndigital.com>  
wrote:

> Sorry if Im stating the obvious.

No problem Matt it is usually the most obvious things that go wrong ;)

> Have you suspended your threads before assigning any of their properties  
> ?
> This can cause problems.

Hmmm yeah I create each thread as

thread := QueryThread.Create(true);  // true = start suspended

I think that should do it, right?

> What does your thread execute do aside from update the GUI in your syn
> routine? Does it access anything else application wide? or any local
> files?

It accesses the two lists which are global. But they are TThreadLists so I  
shouldn't be doing any synchronization.
Each thread accesses the GetInetFile method alot, so this can be the weak  
point of the application. But I cannot synchronize this method, because  
the point of the threads is to make the downloading faster. If each thread  
had to wait for another to finish downloading a page from the internet  
then there would be no point for using threads.

I've read about the WinAPI functions I'm using in this method and they are  
all thread safe, according to MSDN.

Here's the method itself. I'll explain the relevant parts in comments.

var
   ENABLE_CACHING: boolean;  // global variable

function GetInetFile(const fileURL, FileName: String; proxy:  
TProxyAddress): boolean;
const BufferSize = 1024;
var
   hSession, hURL: HInternet;
   Buffer: array[1..BufferSize] of Byte;
   BufferLen: DWORD;
   f: File;
   sAppName,error: string;
   caching: boolean;
   critical: _RTL_CRITICAL_SECTION;   // used for critical section
begin
  Result := False;

  InitializeCriticalSection(critical);  // here I am accessing the  
ENABLE_CACHING
  EnterCriticalSection(critical);       // global variable, so I use a  
critical
  caching := ENABLE_CACHING;            // section for synchronizing
  LeaveCriticalSection(critical);
  DeleteCriticalSection(critical);

  error := '';
  sAppName := ExtractFileName(Application.ExeName);

  if proxy = nil then
    hSession := InternetOpen(PChar(sAppName),  // this function starts the  
session
                 INTERNET_OPEN_TYPE_PRECONFIG, // it should be thread-safe
                nil, nil, 0)
  else
    hSession := InternetOpen(PChar(sAppName),  // configure to use a proxy
                 INTERNET_OPEN_TYPE_PROXY,
                 PChar(proxy^.host + ':' + IntToStr(proxy^.port)), nil, 0);

  if hSession = nil then        // this is for debugging
    error := 'Unable to open Internet connection.';

  try
    if caching then
     hURL := InternetOpenURL(hSession,  // check if URL exists
             PChar(fileURL),            // this should be thread-safe
             nil,0,0,0)
    else     // caching disabled
     hURL := InternetOpenURL(hSession,
             PChar(fileURL),
             nil,0,INTERNET_FLAG_RELOAD,0);

   if hURL = nil then
     error := 'Unable to open URL: ' + fileURL;

   try                // now I open a new file and write the content into it
    AssignFile(f, FileName);
    Rewrite(f,1);
    repeat
       // download file from the internet, this should be thread-safe
       if not InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen)  
then begin
         error := 'Error reading from file: ' + fileURL + #13'Maybe your  
proxy is not working?';
         break
       end;
       BlockWrite(f, Buffer, BufferLen)
    until BufferLen = 0;
    CloseFile(f);
    Result:=True;
   finally
    InternetCloseHandle(hURL)
   end;
  finally
   InternetCloseHandle(hSession)
  end;

  {$IFDEF Debug}
  if error <> '' then
    raise Exception.Create(error)
  {$ENDIF}
end;

In any case, this method is inside a try-except block. So if anything goes  
wrong I will catch the exception.


> Are you using Indy for your sockets? (These are components not classes)
>
> Are you using an activex controls ?


No I'm not using any custom components or libraries, most of the stuff is  
by me or I've found it on the internet (like the GetInetFile method, which  
is from http://delphi.about.com/od/internetintranet/l/aa013001a.htm ). I'm  
trying to use the WinAPI whenever I can, I find it to be more reliable  
than custom components.

The client still hasn't replied (he's from Canada so it's probably still  
Sunday afternoon there :)). I've placed everything in the Execute method  
into a try-except block, hopefully that will do it.
If not I'll try one of the debug libraries suggested by you guys.

Thanks for the help,
Csaba



More information about the Delphi mailing list