From 8e2140fa5eb8a019a5134ce041499d14b7ced7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 29 Apr 2012 20:21:40 +0200 Subject: [PATCH] Fixed a large client side memory leak for app_server memory. * The areas allocated for BBitmaps were never deleted, even though the app_server deleted its part when the memory got freed. * This resulted in a constant memory increase if the application in question would operate on many changing large bitmaps, like photos. * Since the bitmaps are reference counted, we don't actually know when to delete the areas, so that the app_server now notifies the client whenever that is possible. * This might fix #6824. --- headers/private/app/ServerProtocol.h | 8 +++++++- src/kits/app/Application.cpp | 13 +++++++++++-- src/kits/app/ServerMemoryAllocator.cpp | 3 ++- src/kits/interface/Bitmap.cpp | 2 +- src/servers/app/ClientMemoryAllocator.cpp | 2 ++ src/servers/app/ServerApp.cpp | 17 ++++++++++++++++- src/servers/app/ServerApp.h | 4 +++- 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index ef7c4394e5..99537198d7 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2010, Haiku. + * Copyright 2001-2012, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -344,6 +344,12 @@ enum { AS_LAST_CODE }; +// TODO: move this into a private app header, together with the rest of the +// private message definitions in AppDefs.h +enum { + kMsgDeleteServerMemoryArea = '_DSA', +}; + // bitmap allocation flags enum { kAllocator = 0x1, diff --git a/src/kits/app/Application.cpp b/src/kits/app/Application.cpp index e28f48942d..4d68d63422 100644 --- a/src/kits/app/Application.cpp +++ b/src/kits/app/Application.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009, Haiku. + * Copyright 2001-2012, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -601,9 +601,18 @@ BApplication::MessageReceived(BMessage *message) break; case kMsgAppServerRestarted: - { _ReconnectToServer(); break; + + case kMsgDeleteServerMemoryArea: + { + int32 serverArea; + if (message->FindInt32("server area", &serverArea) == B_OK) { + // The link is not used, but we currently borrow its lock + BPrivate::AppServerLink link; + fServerAllocator->RemoveArea(serverArea); + } + break; } default: diff --git a/src/kits/app/ServerMemoryAllocator.cpp b/src/kits/app/ServerMemoryAllocator.cpp index 2518b54ab8..6d34fc238d 100644 --- a/src/kits/app/ServerMemoryAllocator.cpp +++ b/src/kits/app/ServerMemoryAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2012, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -131,6 +131,7 @@ status_t ServerMemoryAllocator::AreaAndBaseFor(area_id serverArea, area_id& _area, uint8*& _base) { + // TODO: why not use a map? for (int32 i = fAreas.CountItems(); i-- > 0;) { area_mapping* mapping = (area_mapping*)fAreas.ItemAt(i); diff --git a/src/kits/interface/Bitmap.cpp b/src/kits/interface/Bitmap.cpp index 09feeda5ff..95d94916a1 100644 --- a/src/kits/interface/Bitmap.cpp +++ b/src/kits/interface/Bitmap.cpp @@ -1186,7 +1186,7 @@ BBitmap::_CleanUp() link.Attach(fServerToken); link.Flush(); - // TODO: we may want to delete parts of the server memory areas here! + // The server areas are deleted via kMsgDeleteServerMemoryArea message fArea = -1; fServerToken = -1; diff --git a/src/servers/app/ClientMemoryAllocator.cpp b/src/servers/app/ClientMemoryAllocator.cpp index 40410615bf..a1ab4cfce8 100644 --- a/src/servers/app/ClientMemoryAllocator.cpp +++ b/src/servers/app/ClientMemoryAllocator.cpp @@ -179,6 +179,8 @@ ClientMemoryAllocator::Free(block* freeBlock) fChunks.Remove(chunk); delete_area(chunk->area); + fApplication->NotifyDeleteClientArea(chunk->area); + free(chunk); } } diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 65e4bfa21e..6f7a6b92d5 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2010, Haiku. + * Copyright 2001-2012, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -484,6 +484,21 @@ ServerApp::RemovePicture(ServerPicture* picture) } +/*! Called from the ClientMemoryAllocator whenever a server area could be + deleted. + A message is then sent to the client telling it that it can delete its + client area, too. +*/ +void +ServerApp::NotifyDeleteClientArea(area_id serverArea) +{ + BMessage notify(kMsgDeleteServerMemoryArea); + notify.AddInt32("server area", serverArea); + + SendMessageToClient(¬ify); +} + + // #pragma mark - private methods diff --git a/src/servers/app/ServerApp.h b/src/servers/app/ServerApp.h index a1baeb275e..84c88afd83 100644 --- a/src/servers/app/ServerApp.h +++ b/src/servers/app/ServerApp.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2010, Haiku. + * Copyright 2001-2012, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -94,6 +94,8 @@ public: BPrivate::BTokenSpace& ViewTokens() { return fViewTokens; } + void NotifyDeleteClientArea(area_id serverArea); + private: virtual void _GetLooperName(char* name, size_t size); virtual void _DispatchMessage(int32 code,