chkaufmann 17 Posted April 12, 2021 When my application runs in an RDP session I get the following error: exception class : EOSError exception message : System Error. Code: 8. Not enough memory resources are available to process this command. 00469607 Logo12.exe System.SysUtils RaiseLastOSError 004696d7 Logo12.exe System.SysUtils Win32Check 00547faa Logo12.exe System.Classes THandleStream.SetSize 005461af Logo12.exe System.Classes TStream.SetSize64 010931ff Logo12.exe ZipForge 7047 TZFBaseArchiver.ForceUpdate 0109a2ea Logo12.exe ZipForge 9754 TZFBaseArchiver.EndUpdate 0109cd7e Logo12.exe ZipForge 10780 TZFBaseArchiver.DeleteFiles 0125d084 Logo12.exe BSStreams 939 TBSZipStreamWriter.Close The problem is, the error doesn't happen on all clients, it even happens on some clients one day and the other day it's not reproducable. What I know is, it happens when the application creates and writes to a local file during a backup and it happens when the function SetEndOfFile(FHandle) is called. The error only apears when I try to save to a local file (located on any \\tsclient\.... path). When I search the internet I don't find anything helpfull except about changing the settings for the Windows pagefile. Unfortunately the provider of our RDP plattform / servers cannot reproduce the problem. So I'm stuck somehow, I don't even understand if the error message points to the real problem. And I don't understand if this is a problem of resources on the local client or on the server where the RDP session is hosted. Something else I know is, that some customers get the same error message when they launch the File Explorer in an RDP session and try to copy a big file from their local drive to the server. Therefor I think the problem cannot be in my application itself, it has to do something with the OS configuration on the server or on the client. So any hint to isolate and fix the problem is welcome. Thanks. Christian Share this post Link to post
SwiftExpat 65 Posted April 12, 2021 Christian, It sounds a lot like desktop heap limitation, most likely on the terminal server. A summary document to describe the problem is here: https://techcommunity.microsoft.com/t5/ask-the-performance-team/sessions-desktops-and-windows-stations/ba-p/372473 The registry reference is here: https://docs.microsoft.com/en-us/troubleshoot/windows-server/performance/desktop-heap-limitation-out-of-memory the fix is in step 4: In the Value data section of the Edit String dialog box, locate the SharedSection entry, and then increase the second value and the third value for this entry. You can bump those values up 512 at a time and see if it helps. Unfortunately it is a reboot each time. For a more scientific approach, I found this from an MVP. https://thundaxsoftware.blogspot.com/2011/10/monitoring-desktop-heap-memory-and.html Share this post Link to post
Guest Posted April 12, 2021 That is not a heap or memory problem, the exception message is red herring and wrong. To understand this first we must understand RDP resource sharing, which is in fact an emulation for local files, this emulation process is done over the RDP protocol, hence you can see that even Windows Explorer block and prevent updating the directory update when you paste files local drive and a directory on RDP, these operation in fact should be only executed using overlapped operation as it might take time to monitor the file over RDP protocol, also there is the permission handling which is different from network shares, also you are using THandleStream this is direct call for file write (and read ...) these API's are not very friendly for net operation, and one in specific is that SetSize, as it is in fact is trying to perform Seek, while Seek internally In Delphi RTL does use SetEndOfFile, on other handle this API perform write (or read !) in Windows RTL, both these operation as executed in an emulated manner over RDP protocol over wire, and there is no timeout for such low level API per se, but the RDP commands does have its own timeout, hence the arbitrary failure, this will happen based on the network speed and busyness. So my thought on this 1) Don't use Seek on TFileStream (or THandleStream..) because it is slow, if the file size small relatively then use TMemoryStream then load or save it in full. 2) Watch and get information on SetSize calls, if they are beyond the specific range (or sizes), to be honest i don't know how much is this relevant, but i have my doubts about the low level API calls if they are being called form the local or remote and where the low level emulation being executed triggering the timeout. 3) don't trust the message "out of memory" when you are using RDP resource shares, (this include printing too), as it might falsely reporting the RDP protocol buffer size not anything else. 4) I am not familiar with Zip Forge, but the sequence of these calls and their naming make me think if this library is RDP resource share friendly, specifically for this case you listed above, i mean this DeleteFiles -> EndUpdate -> ForceUpdate -> SetSize This means some files had been deleted and the overall archive file size need to be truncated, is it possible to write new file instead updating the existing one ? or just need to use overlapped operation and give the RDP protocol time to finish the file size updating. Also this is strange as SetSize based on the operations should be less, we are deleting files, so the cause for out of memory is not clear, unless it is trying to bring the whole file remotely then adjust its size and send the updated version back, which makes some sense, (may be) These were my thoughts and hope they are helps you. Share this post Link to post
chkaufmann 17 Posted April 12, 2021 2 hours ago, Kas Ob. said: This means some files had been deleted and the overall archive file size need to be truncated, is it possible to write new file instead updating the existing one ? or just need to use overlapped operation and give the RDP protocol time to finish the file size updating. I think I can change the code and create the .ZIP as temporary file and then copy/move this file to the local file on \\tsclient\..... - Normally I use CopyFile() or MoveFile(). What works better with the RDP protocol? - When I look at Windows.pas unit there are many variants of these functions. Should I use a different one? Thanks for your help. Regards Christian Share this post Link to post
Guest Posted April 12, 2021 2 minutes ago, chkaufmann said: - Normally I use CopyFile() or MoveFile(). What works better with the RDP protocol? Both will work the same, also using the Delphi RTL or the API directly will be OK, with the same result. (i think) 3 minutes ago, chkaufmann said: - When I look at Windows.pas unit there are many variants of these functions. Should I use a different one? No need, copy or move will do it, but my suggestion is to build the archive file (zip) in memory without disk operation then save it locally or not, again i am not familiar with your zip library and if does allow such usage, also if the archive is very big then building it in memory will take long time on sending, but again it is up to you to measure the size and tune it. My point is against using Seek in general with THandleStreams and files as it is encapsulate hidden read, a full disk operation that have the same delay and latency, on other hand using Seek on RDP resource shares might be buggy to begin, RDP had its share of such bugs over years. Share this post Link to post
chkaufmann 17 Posted April 13, 2021 I changed my code and the error seems to be gone. Thanks a lot. Now my last question is: Are there other potential problems I may have with my application when running in an RDP session? Especially other problems when loading / saving files from local drives? Until now I didn't find a good resource in the internet about where I should be carefull in my application in order to make it run without errors in RDP sessions: Regards Christian Share this post Link to post
Guest Posted April 13, 2021 In my opinion RDP was introduced as (how to put it) as an extension to Windows Explorer, it wasn't intended to deliver stable resource sharing over internet, but RDP allowed initializing and sharing drivers for the user himself, but not for an application, and by user i meant a user using Windows Explorer. Away from you are depending on technology that can fail anytime, and you should rethink how you or your users are depending on it, i think you can extend your application to upload and download files in right manner, by HTTP or IIS or using a web browser after authorization, there is many solution to think about this where you can have peace of mind about its reliability. Share this post Link to post