Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

protect some additional dictionaries #2339

Merged
merged 5 commits into from May 24, 2017
Merged

protect some additional dictionaries #2339

merged 5 commits into from May 24, 2017

Conversation

skurfer
Copy link
Member

@skurfer skurfer commented Apr 12, 2017

I mentioned revisiting this, so here we are.

I’ve seen quite a few crashes (locally and in uploaded reports) when something tries to change a dictionary inside loadIconForObject: (which runs on a background thread).

These are the ones I see regularly. Sadly, I don’t know how we could protect everything that could possibly be accessed via icon loading, but this should cover some common cases.

Seems like we should protect data and meta as well, but in practice, I don’t see any crashes related to those, so I’m leaving them.

these are frequently touched when icons are loaded on background threads
@skurfer
Copy link
Member Author

skurfer commented Apr 13, 2017

Added another one.prefInstances gets updated (during icon loading) by the mail support plug-in. Probably the most common source of crashes for me personally. Glad to finally have a potential answer.

@pjrobertson
Copy link
Member

I guess it's very difficult for you to say for sure, but does this solve the problem? Will this likely cause hangs?

Also I've just checked out QSThreadSafeMutableDictionary (which I added a few years back) and there are a few comments on the gist that we should perhaps update:
https://gist.github.com/steipete/5928916

We could also look at using NSCache: https://developer.apple.com/reference/foundation/nscache

@skurfer
Copy link
Member Author

skurfer commented Apr 18, 2017

I guess it's very difficult for you to say for sure, but does this solve the problem?

I would see it twice a day, but sometimes go weeks in between, so yeah, hard to say. If it helps, the crashes always happen during setObject:forKey:. My theory is that the object previously occupying that spot was already released somewhere, then gets released again when the dictionary doesn’t point to it any more.

Will this likely cause hangs?

I suppose it increases the likelihood. I feel like we’re walking a knife’s edge now between hangs and crashes. 🙁

I’ll look at updating the dictionary class and look at NSCache.

@@ -469,13 +469,13 @@ - (void)setObject:(id)object forMeta:(id)aKey {
}
}

- (NSMutableDictionary *)cache {
- (QSThreadSafeMutableDictionary *)cache {
if (!cache) [self setCache:[NSMutableDictionary dictionaryWithCapacity:1]];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, there's one left.

Can you move the initialization of data, meta and cache in -init ? That would at least make those accessors saner (it's something I did in #2344 but I don't mind rebasing that).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes on this branch are so small. It might be simpler for everyone if I just remove the QSObject changes here and you can do what you think is best to make cache thread-safe on your branch. Let me know if that sounds good.

@@ -105,7 +105,7 @@ typedef struct _QSObjectFlags {

- (void)setDetails:(NSString *)newDetails;

- (NSMutableDictionary *)cache;
- (QSThreadSafeMutableDictionary *)cache;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd prefer that not to appear in the interface. Can you keep it as NSMutableDictionary * here and silence the compiler in the property instead ?

@skurfer
Copy link
Member Author

skurfer commented May 16, 2017

A couple of new self-explanatory commits. I haven’t seen a crash related to icon loading in nearly a month using this, by the way.

@skurfer
Copy link
Member Author

skurfer commented May 17, 2017

If there are any problems with this @tiennou, let me know in the next day or two. I want to get a release out that includes this. The recent changes should address your comments, but will require some rebasing in the QSObject clean-up branch.

@tiennou
Copy link
Member

tiennou commented May 17, 2017

I'm just wondering what the implications of the switch to NSCache is (w.r.t cached things going away under us because memory pressure yadda-yadda). If you're sure it doesn't do weird things though that's fine with me.

@skurfer
Copy link
Member Author

skurfer commented May 18, 2017

If something needs to stay forever, it should probably go in meta. (Something we might consider for infoRecord, but even with that one, in the worst case it gets loaded from disk again.)

@tiennou
Copy link
Member

tiennou commented May 18, 2017

I didn't make myself clear enough : we don't have any control over when an NSCache is cleared. As an example, this can make the Current Selection proxy item lose its cached selection because the OS just decided to clear it because you generated a Quicklook preview for the currently selected 500Mb Photoshop file you've just QSed.

@skurfer
Copy link
Member Author

skurfer commented May 18, 2017

Yeah, I get it, but the chances are pretty low and that’s another one where it will just get repopulated the first time something tries to use it again.

I don’t have strong feelings either way. Do you want me to change it back to QSThreadSafeMutableDictionary?

@tiennou
Copy link
Member

tiennou commented May 18, 2017

I think I'd be more comfortable keeping the dictionary, yes. I don't really want to add another "impossible to reproduce" class of bugs 😜.

@skurfer
Copy link
Member Author

skurfer commented May 18, 2017

OK, force-pushed to remove those last two commits. It’s back to a thread safe dictionary. I also changed the interface (which the compiler isn’t complaining about) and I moved the initialization.

I’ll test it out for a while. Most likely release tomorrow unless I hear screaming from across the Atlantic. 😃

@skurfer skurfer merged commit c3c55a8 into master May 24, 2017
@skurfer skurfer deleted the tsmd branch May 24, 2017 13:04
skurfer added a commit that referenced this pull request May 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants