powered by Jive Software

Bug report: NullPointerException at Roster.java:1648


#1

Don’t know how to reproduce.

Smack version: 4.3.1

Exception:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke interface method 'java.util.List org.jivesoftware.smack.roster.rosterstore.RosterStore.a()' on a null object reference
       at org.jivesoftware.smack.roster.Roster$RosterResultListener.onSuccess(SourceFile:1648)
       at org.jivesoftware.smack.roster.Roster$RosterResultListener.onSuccess(SourceFile:1596)
       at org.jivesoftware.smack.SmackFuture$1.run(SourceFile:151)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
       at java.lang.Thread.run(Thread.java:764)

mapping:

org.jivesoftware.smack.roster.rosterstore.RosterStore -> org.jivesoftware.smack.roster.rosterstore.RosterStore:
    java.util.List getEntries() -> a

#2

Thanks for reporting this. :slight_smile:

One possible way to trigger this is if the RosterStore is set to null while a versioned roster is retrieved. While it is not really someone should ever do, it is trivial to make Smack more robust against this.


#3

Adding info from the 2 crash reports I’ve got:

Both reports include threads having this entry: org.jivesoftware.smack.tcp.XMPPTCPConnection.notifyConnectionError.
I don’t know much of Smack’s internals but, given the correlation, the cause of this crash may be related to a possible racing condition when a Roster response is being consumed just after the connection having been dropped.

I noticed one suspicious thing: my IDE can’t find any usage of the Roster#setRosterStore setter method from either my application of any other library in my dependency graph, suggesting this field is always null. I don’t initialize or even use Roster directly. I do use ChatManager though, which seems to use it.


#4

Confirming: by adding a breakpoint to RosterResultListener#onSuccess, I can see the #rosterStore field is always null after a reload triggered by a connect+login.


#5

stanza ids are unique per connection, right?

I can’t find in AbstractXMPPConnection any code that clears its #syncRecvListeners and #asyncRecvListeners maps upon disconnections. If they’re really not cleared, a mismatched stanza may be delivered to a wrong listener that didn’t timeout yet after disconnecting and connecting the same AbstractXMPPConnection instance.

That would explain why RosterResultListener#onSuccess is getting a stanza that’s not a RosterPackage when it supposedly didn’t make any versioned request (as per Roster#reload's implementation when rosterStore is null)