That's a feature, not a bug. Write-protecting memory areas using mprotect() and the like, and handling the resulting SIGSEGV, is a popular technique for implementing a write barrier needed for generational garbage collection.
I've seen it used before to good effect, but one concern is that it's really easy to write flaky and unsafe signal handlers. Getting that right has never seemed easy to me.
It's very easy to write flaky and unsafe memory management code in general, yet memory management is used with good results in nearly every production system. And there's nothing wrong with using "tricky" OS and hardware services to implement language runtimes and core libraries --- that's what they're there for.