From: <ob...@us...> - 2010-03-09 11:18:53
|
Revision: 12716 http://jvcl.svn.sourceforge.net/jvcl/?rev=12716&view=rev Author: obones Date: 2010-03-09 11:18:46 +0000 (Tue, 09 Mar 2010) Log Message: ----------- Mantis 5001: Potential memory leak Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2010-03-09 11:13:09 UTC (rev 12715) +++ trunk/jvcl/run/JvHidControllerClass.pas 2010-03-09 11:18:46 UTC (rev 12716) @@ -1,4 +1,4 @@ -{----------------------------------------------------------------------------- +{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -784,7 +784,7 @@ end; end; - PnPInfo.Free; + FPnPInfo.Free; inherited Destroy; end; @@ -1699,7 +1699,8 @@ HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); NewList.Add(HidDev); except - // ignore device if unreadable + // ignore device if unreadable but still free used memory + PnPInfo.Free; end; Inc(Devn); end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ob...@us...> - 2011-06-08 14:10:22
|
Revision: 13045 http://jvcl.svn.sourceforge.net/jvcl/?rev=13045&view=rev Author: obones Date: 2011-06-08 14:10:12 +0000 (Wed, 08 Jun 2011) Log Message: ----------- Mantis 5546 : no need to free on exception because the constructor has taken ownership of it Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2011-06-08 13:37:23 UTC (rev 13044) +++ trunk/jvcl/run/JvHidControllerClass.pas 2011-06-08 14:10:12 UTC (rev 13045) @@ -229,6 +229,10 @@ procedure StartThread; procedure StopThread; // Constructor is hidden! Only a TJvHidDeviceController can create a TJvHidDevice object. + // APnPInfo becomes the property of this class, do not try to free it yourself, + // even if this call raises an exception. + // The destructor of this class will take care of the cleanup even when an exception + // is raised (as specified by the Delphi language) constructor CtlCreate(const APnPInfo: TJvHidPnPInfo; const Controller: TJvHidDeviceController); protected @@ -1695,13 +1699,8 @@ // fill in PnPInfo of device PnPInfo := TJvHidPnPInfo.Create(PnPHandle, DevData, PChar(@FunctionClassDeviceData.DevicePath)); // create HID device object and add it to the device list - try - HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); - NewList.Add(HidDev); - except - // ignore device if unreadable but still free used memory - PnPInfo.Free; - end; + HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); + NewList.Add(HidDev); Inc(Devn); end; FreeMem(FunctionClassDeviceData); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ob...@us...> - 2012-05-25 08:18:28
|
Revision: 13302 http://jvcl.svn.sourceforge.net/jvcl/?rev=13302&view=rev Author: obones Date: 2012-05-25 08:18:19 +0000 (Fri, 25 May 2012) Log Message: ----------- Must make sure to call the CancelIO command on all instances. Also, make sure that we sleep when there was a read error or we would trigger 100% CPU usage (Mantis 5749) Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2012-05-25 08:17:19 UTC (rev 13301) +++ trunk/jvcl/run/JvHidControllerClass.pas 2012-05-25 08:18:19 UTC (rev 13302) @@ -507,39 +507,43 @@ begin NameThread(ThreadName); SleepRet := WAIT_IO_COMPLETION; - while not Terminated do - begin - // read data - SleepRet := WAIT_IO_COMPLETION; - FillChar(Report[0], Device.Caps.InputReportByteLength, #0); - if Device.ReadFileEx(Report[0], Device.Caps.InputReportByteLength, @DummyReadCompletion) then + try + while not Terminated do begin - // wait for read to complete - repeat - SleepRet := SleepEx(Device.ThreadSleepTime, True); - until Terminated or (SleepRet = WAIT_IO_COMPLETION); - // show data read - if not Terminated then + // read data + SleepRet := WAIT_IO_COMPLETION; + FillChar(Report[0], Device.Caps.InputReportByteLength, #0); + if Device.ReadFileEx(Report[0], Device.Caps.InputReportByteLength, @DummyReadCompletion) then begin - NumBytesRead := Device.HidOverlappedReadResult; - if NumBytesRead > 0 then - // synchronizing only works if the component is not instanciated in a DLL - if IsLibrary then - DoData - else - Synchronize(DoData); + // wait for read to complete + repeat + SleepRet := SleepEx(Device.ThreadSleepTime, True); + until Terminated or (SleepRet = WAIT_IO_COMPLETION); + // show data read + if not Terminated then + begin + NumBytesRead := Device.HidOverlappedReadResult; + if NumBytesRead > 0 then + // synchronizing only works if the component is not instanciated in a DLL + if IsLibrary then + DoData + else + Synchronize(DoData); + end; + end + else + begin + FErr := GetLastError; + Synchronize(DoDataError); + SleepEx(Device.ThreadSleepTime, True); // avoid 100% CPU usage (Mantis 5749) end; - end - else - begin - FErr := GetLastError; - Synchronize(DoDataError); end; + finally + // cancel ReadFileEx call or the callback will + // crash your program + if SleepRet <> WAIT_IO_COMPLETION then + Device.CancelIO(omhRead); end; - // cancel ReadFileEx call or the callback will - // crash your program - if SleepRet <> WAIT_IO_COMPLETION then - Device.CancelIO(omhRead); end; //=== { TJvHidPnPInfo } ====================================================== This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ob...@us...> - 2012-06-13 13:24:35
|
Revision: 13345 http://jvcl.svn.sourceforge.net/jvcl/?rev=13345&view=rev Author: obones Date: 2012-06-13 13:24:29 +0000 (Wed, 13 Jun 2012) Log Message: ----------- try..finally is cleaner Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2012-06-13 13:12:56 UTC (rev 13344) +++ trunk/jvcl/run/JvHidControllerClass.pas 2012-06-13 13:24:29 UTC (rev 13345) @@ -1699,18 +1699,21 @@ if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin FunctionClassDeviceData := AllocMem(BytesReturned); - FunctionClassDeviceData^.cbSize := SizeOf(TSPDeviceInterfaceDetailData); - if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, - FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then - begin - // fill in PnPInfo of device - PnPInfo := TJvHidPnPInfo.Create(PnPHandle, DevData, PChar(@FunctionClassDeviceData.DevicePath)); - // create HID device object and add it to the device list - HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); - NewList.Add(HidDev); - Inc(Devn); + try + FunctionClassDeviceData^.cbSize := SizeOf(TSPDeviceInterfaceDetailData); + if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, + FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then + begin + // fill in PnPInfo of device + PnPInfo := TJvHidPnPInfo.Create(PnPHandle, DevData, PChar(@FunctionClassDeviceData.DevicePath)); + // create HID device object and add it to the device list + HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); + NewList.Add(HidDev); + Inc(Devn); + end; + finally + FreeMem(FunctionClassDeviceData); end; - FreeMem(FunctionClassDeviceData); end; end; until not Success; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ob...@us...> - 2012-11-05 09:33:38
|
Revision: 13468 http://jvcl.svn.sourceforge.net/jvcl/?rev=13468&view=rev Author: obones Date: 2012-11-05 09:33:31 +0000 (Mon, 05 Nov 2012) Log Message: ----------- Mantis 5894 : Added OnDeviceCreateError so that people can "hook" into the procedure Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2012-10-31 20:51:39 UTC (rev 13467) +++ trunk/jvcl/run/JvHidControllerClass.pas 2012-11-05 09:33:31 UTC (rev 13468) @@ -51,6 +51,7 @@ // forward declarations TJvHidDeviceController = class; TJvHidDevice = class; + TJvHidPnPInfo = class; // the Event function declarations TJvHidEnumerateEvent = function(HidDev: TJvHidDevice; @@ -60,6 +61,7 @@ TJvHidDataEvent = procedure(HidDev: TJvHidDevice; ReportID: Byte; const Data: Pointer; Size: Word) of object; TJvHidDataErrorEvent = procedure(HidDev: TJvHidDevice; Error: DWORD) of object; + TJvHidDeviceCreateError = procedure(Controller: TJvHidDeviceController; PnPInfo: TJvHidPnPInfo; var Handled: Boolean; var RetryCreate: Boolean) of object; // check out test function TJvHidCheckCallback = function(HidDev: TJvHidDevice): Boolean; stdcall; @@ -363,6 +365,7 @@ FDevDataErrorEvent: TJvHidDataErrorEvent; FDevUnplugEvent: TJvHidUnplugEvent; FRemovalEvent: TJvHidUnplugEvent; + FOnDeviceCreateError: TJvHidDeviceCreateError; FDevThreadSleepTime: Integer; FVersion: string; FDummy: string; @@ -427,6 +430,8 @@ property OnEnumerate: TJvHidEnumerateEvent read FEnumerateEvent write SetEnumerate; // the central event for HID device changes property OnDeviceChange: TNotifyEvent read FDeviceChangeEvent write SetDeviceChangeEvent; + // this event is triggered when an error occured while creating a given TJvHidDevice + property OnDeviceCreateError: TJvHidDeviceCreateError read FOnDeviceCreateError write FOnDeviceCreateError; // these events are copied to TJvHidDevices on creation property OnDeviceData: TJvHidDataEvent read FDevDataEvent write SetDevData; property OnDeviceDataError: TJvHidDataErrorEvent read FDevDataErrorEvent write SetDevDataError; @@ -774,18 +779,26 @@ // if device is plugged in create a checked in copy if IsPluggedIn then begin - Dev := TJvHidDevice.CtlCreate(FPnPInfo, FMyController); - // make it a complete clone - Dev.OnData := TmpOnData; - Dev.OnUnplug := TmpOnUnplug; - Dev.ThreadSleepTime := ThreadSleepTime; - FList.Items[I] := Dev; - // the FPnPInfo has been handed over to the new object - FPnPInfo := nil; - if IsCheckedOut then - begin - Dec(FNumCheckedOutDevices); - Inc(FNumCheckedInDevices); + try + Dev := TJvHidDevice.CtlCreate(FPnPInfo, FMyController); + // make it a complete clone + Dev.OnData := TmpOnData; + Dev.OnUnplug := TmpOnUnplug; + Dev.ThreadSleepTime := ThreadSleepTime; + FList.Items[I] := Dev; + // the FPnPInfo has been handed over to the new object + FPnPInfo := nil; + if IsCheckedOut then + begin + Dec(FNumCheckedOutDevices); + Inc(FNumCheckedInDevices); + end; + except + on EControllerError do + begin + FList.Delete(I); + Dec(FNumUnpluggedDevices); + end; end; end else @@ -1678,6 +1691,8 @@ BytesReturned: DWORD; HidDev: TJvHidDevice; PnPInfo: TJvHidPnPInfo; + Handled: Boolean; + RetryCreate: Boolean; begin if not IsHidLoaded then Exit; @@ -1707,9 +1722,30 @@ // fill in PnPInfo of device PnPInfo := TJvHidPnPInfo.Create(PnPHandle, DevData, PChar(@FunctionClassDeviceData.DevicePath)); // create HID device object and add it to the device list - HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); - NewList.Add(HidDev); - Inc(Devn); + RetryCreate := False; + HidDev := nil; + repeat + try + HidDev := TJvHidDevice.CtlCreate(PnPInfo, Self); + except + on EControllerError do + if Assigned(OnDeviceCreateError) then + begin + Handled := False; + OnDeviceCreateError(Self, PnPInfo, Handled, RetryCreate); + if not Handled then + raise; + end + else + raise; + end; + until not RetryCreate; + + if Assigned(HidDev) then + begin + NewList.Add(HidDev); + Inc(Devn); + end; end; finally FreeMem(FunctionClassDeviceData); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ob...@us...> - 2013-01-15 13:56:57
|
Revision: 13488 http://jvcl.svn.sourceforge.net/jvcl/?rev=13488&view=rev Author: obones Date: 2013-01-15 13:56:50 +0000 (Tue, 15 Jan 2013) Log Message: ----------- Mantis 5894: One must always increment the device index in order to test the next device Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2013-01-08 06:29:08 UTC (rev 13487) +++ trunk/jvcl/run/JvHidControllerClass.pas 2013-01-15 13:56:50 UTC (rev 13488) @@ -1742,16 +1742,15 @@ until not RetryCreate; if Assigned(HidDev) then - begin NewList.Add(HidDev); - Inc(Devn); - end; end; finally FreeMem(FunctionClassDeviceData); end; end; end; + + Inc(Devn); until not Success; SetupDiDestroyDeviceInfoList(PnPHandle); end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ob...@us...> - 2013-01-15 14:20:27
|
Revision: 13489 http://jvcl.svn.sourceforge.net/jvcl/?rev=13489&view=rev Author: obones Date: 2013-01-15 14:20:16 +0000 (Tue, 15 Jan 2013) Log Message: ----------- Mantis 5926: Fixed memory leaks Modified Paths: -------------- trunk/jvcl/run/JvHidControllerClass.pas Modified: trunk/jvcl/run/JvHidControllerClass.pas =================================================================== --- trunk/jvcl/run/JvHidControllerClass.pas 2013-01-15 13:56:50 UTC (rev 13488) +++ trunk/jvcl/run/JvHidControllerClass.pas 2013-01-15 14:20:16 UTC (rev 13489) @@ -779,6 +779,7 @@ // if device is plugged in create a checked in copy if IsPluggedIn then begin + Dev := nil; try Dev := TJvHidDevice.CtlCreate(FPnPInfo, FMyController); // make it a complete clone @@ -797,6 +798,7 @@ on EControllerError do begin FList.Delete(I); + Dev.Free; Dec(FNumUnpluggedDevices); end; end; @@ -1608,9 +1610,9 @@ // set to uncontrolled FMyController := nil; if IsCheckedOut then - DoUnplug // pull the plug for checked out TJvHidDevices - else - Free; // kill TJvHidDevices which are not checked out + DoUnplug; // pull the plug for checked out TJvHidDevices + + Free; // Always free, which will kill TJvHidDevices which are not checked out end; end; FList.Free; @@ -1779,7 +1781,10 @@ DoRemoval(HidDev); // delete from list if not HidDev.IsCheckedOut then + begin FList.Delete(I); + HidDev.Free; + end; Changed := True; end; end; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |