The unusual part is most likely outside of Stdio.Buffer. At various spots in the code we call io_*() functions directly to manipulate Buffer objects. At least one of those spots is calling some of the PIKEFUNs after the object has been destructed.
Then that would be a bug.
Come to think of it, that might be the Shuffler code. We use callbacks there, and the callbacks are PIKEFUNs, I believe.
One thing I can confirm though, the destruct-guards I put in place now work and solve the coredump problems. Normally I would have gathered at least six coredumps in 24 hours.
They may work, but only in the sense that you are shielding yourself from the worst consequences of undefined/use-after-free/... memory access. Both your changes, the one checking io->output's type to be PIKE_T_FUNCTION and the CHECK_DESTRUCTED stuff are of this nature, you are guarding against stuff that is not supposed to happen.
What's more, io->output is exported as a mapped variable, albeit as a private one, meaning practically only the GC can see it. "User-accessible" svalues are not supposed to contain PIKE_T_FREE or PIKE_T_UNKNOWN, really. With the private map I think we should really treat it as user-accessible in this regard, if only to not constitute a special case for mapped (but private) variables.
Your changes should thus all be reverted and the real issue(s) should be identified and fixed.