Re: [twsocket] Problem with TFtpClient - Access Violation error
Hello, Finally source of the problem found. As I suspected, FtpClient doing a Free of the assigned MemoryStream. TCustomFtpCli.DoGetAsync() procedure line no: 5211 { open the destination file } { Don't open a file if we're on FDisplayFileFlag } if not FDisplayFileFlag then try DestroyLocalStream; // <--- HERE THIS LINE FREE THE ASSIGNED MEMORYSTREAM if FResumeAt <= 0 then begin if not Assigned(FLocalStream) and not FStreamFlag then begin FLocalStream := OpenFileStream(FLocalFileName, fmCreate); { V2.105 } if FShareMode <> 0 then begin { Not default mode, need to close and reopen file with } { the given mode } FreeAndNil(FLocalStream); FLocalStream := OpenFileStream(FLocalFileName, fmOpenWrite + FShareMode); end; end; end What I did to solve my problem is to change my code in OnRequestDone() procedure as below: ftpDirAsync: begin if not Assigned(cls.DirStream) then begin AddToLog(cls, '*** ERROR: LocalStream not assigned'); Exit(); end; if cls.DirStream.Size = 0 then begin AddToLog(cls, '*** ERROR: DirStream = 0'); Exit(); end; cls.FtpList := TStringList.Create; try // finally // load FTP file directory, make sure it's not empty SetString(TempString, PAnsiChar(cls.DirStream.Memory), cls.DirStream.Size); cls.FtpList.Text := TempString; cls.FileNameList := TStringList.Create(); try GetFileNamesFromFtpList(cls.FtpList, cls.FileNameList, ' '); cls.DownloadList.Clear(); // AddToLog(cls.Id, 'File download filter: ' + cls.DownloadFileMask); FilterFilesInList(cls.FileNameList, cls.DownloadList, cls.DownloadFileMask); finally cls.FileNameList.Free(); end; finally cls.FtpList.Free(); cls.Ftp.LocalStream := nil; // <--- HERE THIS LINE ADDED AND PROBLEM SOLVED cls.DirStream.Clear(); //cls.DirStream := nil; //cls.FStreamCreated := False; end; cls.Ftp.TypeSetAsync(); end; I didn't see anywhere that TFtpClient.LocalStream is to be assigned a nil right after its usage, but it seems to be the case. Just a feedback for mailing list archieves. Thanks & regards, Ertan Küçükoğlu -Original Message- From: TWSocket [mailto:twsocket-boun...@lists.elists.org] On Behalf Of Ertan Küçükoğlu Sent: Wednesday, September 14, 2016 3:27 PM To: 'ICS support mailing' Subject: Re: [twsocket] Problem with TFtpClient - Access Violation error > Yes, but when you read or write a stream, the next read/write position > is where you last left it, and you probably read > beyond the stream end, and then got an AV trying to write there. > > Clear the stream before every request. Something is odd on my side and I cannot find it. This is a single form application. Current code does below. 1- Create a MemoryStream and TFtpClient at the time form created. 2- It is only OnError and OnRequestDone events are assigned to FtpClient component 3- MemoryStream is not touched if there is an error condition with the download (I am not getting any error for the first pass in terms of ftp download sequence anyway) 4- Do a MemoryStream.Clear just before each pass, before even starting a connection (and I get AV right on the line I am doing Clear() for second pass. First pass is fine) 5- Ftp.LocalStream is assigned to MemoryStream for each pass. 6- Do a MemoryStream.Free when form destroy (and I get another AV there if there is one or more pass trials) - There is no MemoryStrem.Free (or Ftp.LocalStream.Free) anywhere in my code other than form destroy. - If it is not created, I would be getting an AV for the first pass. - I see Assigned(MemoryStream) = True if I put a break point in the debugging - I see MemoryStream having value of '()' in the Watch List before calling MemoryStream.Clear() Additionally, I see below code in TFtpClient code. I have no idea when that is triggered. TCustomFtpCli.DestroyLocalStream procedure around line no 2536: if Assigned(FLocalStream) and (FStreamFlag = FALSE) then begin FLocalStream.Free; FLocalStream := nil; end; Is it possible that run-time create of TFtpClient is setting FStreamFlag to False? However, I should see MemoryStream to be nil in the Watch List. My code which is using the MemoryStream is like below. "Cls" is a class of TMyClass that I defined to hold several other variables: ftpDirAsync: begin if not Assigned(cls.DirStream) then begin AddToLog(cls, '*** ERROR: LocalStream not assigned'); Exit();
Re: [twsocket] Problem with TFtpClient - Access Violation error
> Yes, but when you read or write a stream, the next read/write position is where you last left it, and you probably read > beyond the stream end, and then got an AV trying to write there. > > Clear the stream before every request. Something is odd on my side and I cannot find it. This is a single form application. Current code does below. 1- Create a MemoryStream and TFtpClient at the time form created. 2- It is only OnError and OnRequestDone events are assigned to FtpClient component 3- MemoryStream is not touched if there is an error condition with the download (I am not getting any error for the first pass in terms of ftp download sequence anyway) 4- Do a MemoryStream.Clear just before each pass, before even starting a connection (and I get AV right on the line I am doing Clear() for second pass. First pass is fine) 5- Ftp.LocalStream is assigned to MemoryStream for each pass. 6- Do a MemoryStream.Free when form destroy (and I get another AV there if there is one or more pass trials) - There is no MemoryStrem.Free (or Ftp.LocalStream.Free) anywhere in my code other than form destroy. - If it is not created, I would be getting an AV for the first pass. - I see Assigned(MemoryStream) = True if I put a break point in the debugging - I see MemoryStream having value of '()' in the Watch List before calling MemoryStream.Clear() Additionally, I see below code in TFtpClient code. I have no idea when that is triggered. TCustomFtpCli.DestroyLocalStream procedure around line no 2536: if Assigned(FLocalStream) and (FStreamFlag = FALSE) then begin FLocalStream.Free; FLocalStream := nil; end; Is it possible that run-time create of TFtpClient is setting FStreamFlag to False? However, I should see MemoryStream to be nil in the Watch List. My code which is using the MemoryStream is like below. "Cls" is a class of TMyClass that I defined to hold several other variables: ftpDirAsync: begin if not Assigned(cls.DirStream) then begin AddToLog(cls, '*** ERROR: LocalStream not assigned'); Exit(); end; if cls.DirStream.Size = 0 then begin AddToLog(cls, '*** ERROR: DirStream = 0'); Exit(); end; cls.DirStream.Seek (0, soFromBeginning); cls.FtpList := TStringList.Create; try // finally // load FTP file directory, make sure it's not empty cls.FtpList.LoadFromStream(cls.DirStream); cls.FileNameList := TStringList.Create(); try GetFileNamesFromFtpList(cls.FtpList, cls.FileNameList, ' '); cls.DownloadList.Clear(); FilterFilesInList(cls.FileNameList, cls.DownloadList, cls.DownloadFileMask); finally cls.FileNameList.Free(); end; finally cls.FtpList.Free(); end; Just cannot see where the problem is. Thanks for all your help. -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
Re: [twsocket] Problem with TFtpClient - Access Violation error
> It is created for sure. I create the stream once when application > started and it is Freed at application close. It maybe that I am > not clearing and resetting. Yes, but when you read or write a stream, the next read/write position is where you last left it, and you probably read beyond the stream end, and then got an AV trying to write there. Clear the stream before every request. Angus -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
Re: [twsocket] Problem with TFtpClient - Access Violation error
-Original Message- From: TWSocket [mailto:twsocket-boun...@lists.elists.org] On Behalf Of Angus Robertson - Magenta Systems Ltd Sent: Wednesday, September 14, 2016 10:33 AM To: twsocket@lists.elists.org Subject: Re: [twsocket] Problem with TFtpClient - Access Violation error > > I have no problem at first pass. File is downloaded just fine. > > Second pass, > > and I get that error. Error is raised after I call "Ftp.DirAsync()". > > You are probably not freeing the stream after reading it during the first pass, and trying to use it a second time without clearing and resetting it. Or freeing the stream and not recreating it. > > Angus It is created for sure. I create the stream once when application started and it is Freed at application close. It maybe that I am not clearing and resetting. Will try that and post result Thanks. -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
Re: [twsocket] Problem with TFtpClient - Access Violation error
> I have no problem at first pass. File is downloaded just fine. > Second pass, > and I get that error. Error is raised after I call > "Ftp.DirAsync()". You are probably not freeing the stream after reading it during the first pass, and trying to use it a second time without clearing and resetting it. Or freeing the stream and not recreating it. Angus -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
[twsocket] Problem with TFtpClient - Access Violation error
Hi, Using Delphi 10.1 Starter Edition. ICS 8, subversion revision 1284 (latest as far as I can tell). I am trying to use TFtpClient in Async mode. Application creates TFtpClient at run-time. It is used to download file(s) at given intervals non-stop (7/24). I do not assign any option, or change any parameter value when I create TFtpClient at run-time. I simply couldn't solve my problem of Access Violation error. It maybe my code causing such an error. Though, I wanted to get a second opinion. I have no problem at first pass. File is downloaded just fine. Second pass, and I get that error. Error is raised after I call "Ftp.DirAsync()". I have following lines before I call Directory listing: ftpCwdAsync: begin Ftp.HostFileName := EmptyStr; Ftp.LocalFileName := EmptyStr; if not Assigned(DirStream) then DirStream := TMemoryStream.Create(); Ftp.LocalStream := DirStream; Ftp.DirAsync(); end; Some digging in code and I ended up below lines. OverbyteIcsFtpCli.pas Line: 2603 procedure TCustomFtpCli.LocalStreamWrite(const Buffer; Count : Integer); begin FLocalStream.WriteBuffer(Buffer, Count); end; I am creating DirStream in OnCreate procedure of the form. Above line which create it in case it is not already is added later when I could not solve AV errors. I simply could not understand what is the problem here. Any help is appreciated. Regards, Ertan Küçükoğlu -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be