Jump to content
chkaufmann

Problem with local resources in RDP Session

Recommended Posts

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

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

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
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
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

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×