复杂的多线程代码中的安全网?

Sud*_*shu 4 c debugging multithreading assert kernel

作为一名开发人员刚刚在一个项目中编写了数千行复杂的多线程"C"代码,并且将来会被其他几个不熟悉此代码的开发人员进行增强,修改等等,我想找出你们试图在这些代码中添加什么样的安全网?作为一个例子,我可以这样做:

  1. 为锁定保护的结构成员定义访问器宏,该成员声明保持相应的锁定.这清楚地表明,对于不熟悉此代码的任何人,这些成员都受到锁定保护.
  2. 应该使用一些自旋锁调用的函数,断言螺旋锁被保持.

您在已编写的多线程代码中添加了哪些安全网?
当其他开发人员修改此类代码时,您遇到了哪些问题?
你在这些代码中加入了什么样的调试工具?

感谢您的意见.

小智 6

我们在产品中做了很多事情(一个旨在帮助您找到应用程序中的并发错误的虚拟机管理程序),它们通常更有用.请注意,我们在代码本身中执行这些操作(因为它是一个高度并发的软件),并且无论您是否编写并发代码,其中一些都很有用.

  • 和你一样,我们有能力断言(lock_held(...))并使用它.

  • 我们也(因为我们有自己的调度程序)可以为那些(罕见的)情况断言(single_threaded()),在这种情况下我们指望系统中没有其他线程处于活动状态.

  • 从一个线程到另一个线程的内存损坏是很常见的(并且很难调试)所以我们做了两件事来解决这个问题:在我们的线程堆栈中撒了一些神奇的cookie.我们定期(在我们的get_thread_id())函数中调用"validate_thread_stack()"函数来检查这些cookie以确保堆栈没有损坏.

  • 我们的malloc在malloc内存块之前和之后粘贴魔术饼干,并免费检查这些.如果有人超出他们的数据,这些可以用来尽早发现腐败.

  • 在free()上,我们在内存中创建了一个众所周知的模式(在我们的例子中是0xdddd ...).这很好地腐蚀了任何一个悬挂指针留在那个记忆区域的人.

  • 我们在线程堆栈底部附近有一个保护页面(一个未映射到地址空间的内存页面).如果线程超出其堆栈,我们通过页面错误捕获它并放入我们的调试器.

  • 我们的锁是见证的.查看FreeBSD锁定见证代码.它就像那样但是自制软件.基本上,见证代码是一种通过查看锁定采集图中的周期来检测潜在死锁的轻量级方法.

  • 我们的锁也包含了访问器,记录了获取和释放的文件/行号.对于双重解锁或双锁,您可以获得关于螺丝拧紧的漂亮调试信息.

  • 我们的锁也是异形的.一旦你的代码工作,你希望它运作良好.我们跟踪通常的事情,例如收购多少次,获得它需要多长时间.

  • 在我们的系统中,我们期望锁不被争用(我们以这种方式仔细设计了代码).因此,如果您在我们的系统中等待超过一秒或两秒的旋转锁定,您将被放入调试器中,因为它很可能不是一件好事.

  • 我们要原子更新的变量包含在C struct的内部.这样做的原因是为了防止混淆代码的好用:atomic_increment(&var); 并且使用var ++.我们很难编写后面的代码.

  • 我们的代码库中禁止使用"volatile",因为编译器模糊地实现了它.尝试拼凑同步是一种糟糕的方式.

  • 当然还有代码审查.如果你无法向同事解释你的并发假设和锁定纪律,那么代码肯定存在问题:-)