#panic #arena #longjmp #setjmp #call-stack

panic-room

使用 setjmp/longjmp 和区域进行的恐慌处理实验

1 个不稳定版本

0.1.0 2024年7月2日

#116 in 内存管理

MIT/Apache

10KB
166

Panic Room

这是非 unwinding 抛出异常处理的一个小实验。

想法是将类似区域的东西附加到 sj/lj 上,使得

  • 你可以使用 panic=abort 编译,但是...
  • 在一个 "房间" 内,它实际上永远不会终止,它会恢复
  • 你可以在房间内分配、获取、借用和修改借用东西
  • 所有分配的东西在成功 抛出异常恢复时都会被销毁
  • 如果那些东西有析构函数,它们也会像平常一样运行

这是一种类似半事务的微型,类似于 catch-unwind,但没有实际的 unwinding,只是 sj/lj。SEH 的一个奇怪的突变亲属。

考虑事项

  • 我不确定将内存分配与这种控制方式连接起来是否有理由。也许这两部分应该保持独立。我认为将区域堆栈、jmp_buf 堆栈、恐慌处理程序和析构函数全部纠缠在一起可能是方便的,但我可能是在想象。

限制

  • 由于无法访问单个内部 API,它无法重置恐慌编号,因此它将永远认为它仍然在恐慌。这只是一个在 stdlib 中的数字。它应该由想要掌握自己命运的人进行调整。如果您知道如何访问它,请发送补丁。

  • “区域”根本不是区域,它是一个 vec-refcell-option-box-dyn-any 东西。仅仅足以绘制正确的 API。如果您想让它像真正的区域一样运行,我怀疑您需要更多的 unsafe 代码。就目前而言,我仅在 sj/lj 上使用 unsafe。

  • 每个人都认为 sj/lj 在本质上是不安全的和糟糕的。好吧,是的,但 unwinding 几乎一样糟糕,并且它还会生成大量的代码用于着陆垫,并让你不得不怀疑哪些代码路径将 unwinding 并在什么半构造状态上运行析构函数。使用这个 crate,析构函数仅在您的代码的愉快路径上运行,在 您在房间中分配的对象 的悲伤路径上,以及在房间的生命结束时运行;想法是让您在愉快的路径中不必太费心考虑析构函数(并且也不必进行代码生成着陆垫)。因此,您的代码 "稍微更原子",尽管当然它仍然可能由于 longjmp 而在执行过程中停止。

  • 为了不关心析构函数在结束时运行,您的对象通常会存活更长时间(直到结束!)除非您在句柄上调用 Room::take 并丢弃结果。这样您可以强制析构函数提前运行。

依赖项

~0–1.9MB
~36K SLoC