Thank you Jindong Huang, this last fix makes a lot of sense to me. Here's a more complete explanation to make it clear to reviewers and anyone else looking at this. The typemap in the fix above marked with _CLOSED is used specifically on close calls for Java handles. The SWIG native code expansion for Cursor:close is shown below as a sample case, it's slightly cleaned up from lang/java/wiredtiger_wrap.clang/java/wiredtiger_wrap.c. The priv = NULL; line that is proposed to be removed in is marked with a comment.
arg2 = *(struct __wt_cursor **)&jarg1;
"cursor" " is null");
savesess2 = arg2->session;
jcb2 = (JAVA_CALLBACK *)(((WT_CURSOR *)arg2)->lang_private);
arg1 = *(struct __wt_cursor **)&jarg1;
"self" " is null");
result = (int)(arg1)->close(arg2);;
if (result != 0 && result != WT_NOTFOUND)
cursorCloseHandler(jenv, savesess2, jcb2);
((WT_CURSOR )arg2)->lang_private = NULL; /****** This is the errant line ******/
And that code more or less reduces to:
jcb2 = cursor->lang_private;
closeHandler(jenv, session, jcb2);
cursor->lang_private = NULL; /******* This is the errant line ******/
Now the problem is quite apparent: cursor->close frees the storage associated with cursor, so touching it (NULL-ing lang_private) leads to undefined behavior. This is a problem with the expansion for Cursor.close as well as Session and Connection close.
Jindong Huang, I'll get a pull request reviewed. Thank you for your persistence!