New issue
Advanced search Search tips

Issue 733016 link

Starred by 2 users

Issue metadata

Status: Archived
Owner:
Closed: Sep 24
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 3
Type: Bug



Sign in to add a comment

Potential memory leak in -[NSImage canInitWithPasteboard:pb].

Project Member Reported by erikc...@chromium.org, Jun 13 2017

Issue description

I've been looking at sources of browser memory bloat by using native heap profiling on my own browser. Full details:
https://docs.google.com/document/d/1fN5balfyrd7sRpd6DRaUI1TwoOwYjLyRSd7mwZT5US8/edit#

Over the course of 1 week, the browser process created ~1k PasteboardCache objects that it did not destroy. This is suggestive of a large leak. 

Each screenshot shows:
  1) # of objects created [that have not been destroyed]
  2) The stack trace of the code that created the object.

In this case, it looks like -[NSImage canInitWithPasteboard:pb] creates a unique pasteboard, which leaks some state. 

Next steps would be to create a test app and see if calling this method in a tight loop results in a large leak, and if so, filing a radar against apple.
 
Screen Shot 2017-06-13 at 4.19.56 PM.png
330 KB View Download

Comment 1 by tapted@chromium.org, Jun 16 2017

Owner: erikc...@chromium.org
Status: Assigned (was: Untriaged)
[mac triage] (assigning based on git-blame - https://codereview.chromium.org/2227083003 )

Random guess: it's the `canInitWithPasteboard` line?

  NSPasteboard* pb = GetPasteboard();
  if (pb && [NSImage canInitWithPasteboard:pb])

Looks like, for some reason, canInitWithPasteboard decides to create a new, unique pasteboard that's never released.

Comment 2 by borisv@chromium.org, Jul 17 2017

Owner: borisv@chromium.org

Comment 3 by borisv@chromium.org, Jul 18 2017

+[NSImage canInitWithPasteboard:] creates large memory objects, attached to the autorelease pool. I was able to reproduce this easily with the code below. Adding autorelease pool though stops the leak. Also, the larger the object in the keyboard, the worse the leak is (e.g. image is way worse than text). The screenshot is for text. For images, my machines crashes very fast with that code, so taking a screenshot was not reliable. Most likely we are missing an autorelease pool. This could be common problem across the code, as Cocoa expects autorelease pools to be around.

  NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
  time_t end = time(NULL) + 30;
  while (time(NULL) < end) {
//  @autoreleasepool {
      if (pasteboard && [NSImage canInitWithPasteboard:pasteboard]) {
      }
//  }
  }
Screen Shot 2017-07-17 at 8.44.19 PM.png
74.2 KB View Download
Theoretically, each thread with an NSRunLoop should have an autoreleasepool. The image of the stack trace in the opening comment shows that this code is being run from a CFRunLoop. Is it possible that even with the autoreleasepool, there's a slow leak of other objects? 

The stack trace seems to suggest that canInitWithPasteboard: results in the creation of a unique pasteboard, which in turn makes some type of pasteboard cache, which seems to be leaking?

Comment 5 by borisv@chromium.org, Jul 18 2017

More likely there is some special object in the clipboard. When I tried with  text and images, I got different stack trace than the one attached in the bug.

[NSPasteboard generalPasteboard] does not seem to leak. I have not tried it in multiple threads, though. I can verify if there is a real autorelease there. One more thing is that we have zombies - we keep the last 100 or 1000 objective-c object alive intentionally. This could explain why it appears as leak.

Comment 6 by borisv@chromium.org, Jul 18 2017

By the way, it is also possible that +[NSImage canInitWithPasteboard:] creates a copy of the pasteboard only when it is run in a separate thread. That object may leak, or be destroyed when the thread is stopped (that may not be detected by memory infra).
Labels: Performance-Memory
Status: Archived (was: Assigned)

Sign in to add a comment