Search code examples
windowsmemory-leaksdwmbsod

DWM Leaks Memory When No Monitor Connected Windows 8


Simply, if no monitor connected and you are doing some "windows" operation on windows 8 embedded, dwm.exe starts allocating memory and never stops.

to regenerate and show you all the problem, i have written an application which is doing "Create a new Form and show it, if there is one created close it first"

public partial class PopupWindows : Form
{
    private Timer _t;
    private Form _form;
    public PopupWindows()
    {
        InitializeComponent();
        this.Size = new Size(500, 500);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        _t = new Timer();
        _t.Tick += (o, ea) =>
        {
            _form?.Close();
            (_form = new Form() { Size = this.Size }).Show();
        };
        _t.Interval = 1000;
        _t.Enabled = true;
    }
}

if you run this application and plug out the monitor, dwm start allocating pages here is the output from pslist -m when the monitor connected

Name                Pid      VM      WS    Priv Priv Pk   Faults   NonP Page
dwm                 840  123528   14400   11264   13044    55125      7  212

after some time but still the monitor connected

dwm                 840  117144   15808   12732   13044    94051      7  200

disconnecting monitor and dwm.exe start allocating

dwm                 840  214660   14444   12664   13044   137409     13  400

below is the output where you can see allocation dwm.exe doing

C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  251956   14460   12740   13044   137413     16  477
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  251956   14460   12740   13044   137413     16  477
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  251956   14460   12740   13044   137413     16  477
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  252964   14460   12740   13044   137413     16  479
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  252964   14460   12740   13044   137413     16  479
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  253972   14460   12744   13044   137413     16  481
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  253972   14460   12744   13044   137413     16  481
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  254980   14460   12744   13044   137413     16  483

and this strange act dwm doing never stops till you connect a monitor or doing vnc connection to the computer.

after some time on operation without monitor, every os component starts to complain about memory and a blue screen of death occurs at the end.

let me show you the last one

dwm                 840  807516   15624   14216   17240   147413     50 1603

here is the output showing how many minutes my popupwindows.exe running

Name                Pid Pri Thd  Hnd   Priv        CPU Time    Elapsed Time
PopupWindows       2052   6   4  138   9468     0:00:00.140     0:23:07.332

as you can see, after about 20 minutes without having a monitor on the device, dwm.exe using 807516 bytes VM and 1603 pages.


Solution

  • Acting like what vnc doing (copying whole screen bitmap to application memory regularly) solved the dwm's allocation problem (which i think dwm caches its outputs but no one come and ask for the changes so it keeps all of them in the memory and never cleans).

    below is the application which starts hidden and regularly copying screen image into app memory

    public partial class HiddenForm : Form
    {
        IntPtr _this;
    
        private System.Windows.Forms.Timer _timer;
        private Bitmap _bmp = null;
        public HiddenForm()
        {
            this.Visible = false;
            this.ShowInTaskbar = false;
            this.FormBorderStyle = FormBorderStyle.None;
            this.HandleCreated += (s, e) => _this = this.Handle;
            this.Load += (s, e) => this.Size = new Size(0, 0);
            CreateHandle();
            CreateControl();
    
            _timer = new System.Windows.Forms.Timer();
            _timer.Tick += _timer_Tick;
            _timer.Interval = 2000;
            _timer.Start();
        }
    
        private void _timer_Tick(object sender, EventArgs e)
        {
            if (Screen.PrimaryScreen == null)
                return;
    
            if (_bmp == null)
            {
                using (Graphics g = CreateGraphics())
                {
                    _bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, g);
                }
            }
            using (Graphics grp = Graphics.FromImage(_bmp))
            {
                grp.CopyFromScreen(0, 0, 0, 0, _bmp.Size);
            }
        }
    }
    

    here is the output after starting my app

    Name                Pid      VM      WS    Priv Priv Pk   Faults   NonP Page
    dwm                 832  117876   20188   19624   35004   184497      7  185
    

    killing my app with pskill waiting a while

    dwm                 832  182388   20264   19852   35004   421343     11  317
    

    it starts increasing to re check our app i started it again by typing

    C:\HiddenForm.exe
    

    and dwm.exe memory allocation magically downed.

    dwm                 832  126384   27900   27364   35144   556729      7  187