【问题标题】:C: Doing something when the program exitsC:程序退出时做某事
【发布时间】:2011-05-21 14:05:16
【问题描述】:

在 C 语言中,如果我的应用程序意外结束,我可以在此之前调用一个函数吗?我正在将一个标志写入数据库(processRunning = 1),以防止其他应用程序启动类似的进程。当应用程序结束时,它不会改变那个标志。

【问题讨论】:

    标签: c exit


    【解决方案1】:

    查看 C 标准库的 atexit API。

    【讨论】:

    • 这不是解决方案。它不会保护您免受异常终止。 atexit 函数在实践中基本上是无用的,除了在永远不会变大或变成库的小程序中,它的使用可能应该被认为是有害的,因为它必然涉及全局变量/全局状态。
    • 你们可能都已经知道这一点,但是网络中断和电源故障之类的事情可能会阻止这种代码的运行。每 'n' 分钟向数据库写入时间戳,并让数据库在无时间戳的 'n + m' 分钟后清理废弃的标志可能更健壮。
    • 感谢您提供非常有用的信息。你应该考虑的事情太多了。在我的情况下,上述解决方案完全足够,因为进程运行时间永远不会超过 2 分钟。我检查一个进程是否运行超过它会被自动杀死。
    • @Catcall:基于轮询的解决方案丑陋,浪费资源,并且健壮性差。正确的解决方案是使用一种锁定机制,当进程死亡或机器重新启动时,操作系统会自动解锁。
    • @R.:我的印象是 OP 向数据库写入的内容不仅仅是标志。如果他是,让数据库清理它是很有意义的。操作系统通常不会提供任何帮助。但如果数据库的唯一用途是存储标志——这似乎是使用数据库的一个奇怪原因——那么你是对的。
    【解决方案2】:

    在 POSIX 上,正确的解决方案是在共享内存中使用强大的互斥锁来保护数据。如果您的进程因持有一个健壮的互斥锁而死,另一个试图锁定互斥锁的程序不会死锁,而是返回EOWNERDEAD,然后它有机会清理受互斥锁保护的状态并调用pthread_mutex_consistent

    编辑:如果您只想阻止程序的多个实例运行,肯定有更好/更简单的方法,例如锁定数据库文件。

    【讨论】:

      【解决方案3】:

      如果您的应用程序正常终止,它将运行通过atexit 注册的函数。这是一个标准功能,可在Windowsunix 和所有其他平台以及C++ 中使用。

      请注意,“正常终止”是指通过调用exit() 或从main() 返回。如果您的应用程序通过abort()_exit() 终止,或者如果它被立即从外部杀死,它可能没有机会进行任何清理。可能有更好的方法,可能在包装程序中设置和清除标志,无论您的程序如何终止,或者完全放弃这个标志。

      【讨论】:

      • 感谢 Gilles 的额外建议。我在想……类似于让应用每隔几秒检查一次附加到特定 PID 的进程是否仍在运行。
      • 一种解决方案可能是涉足捕捉信号。 (我认为这不适用于 Windows。)
      • @Frank:请注意,通过 PID 进行检查并非万无一失。 PID 可以被不相关的进程快速重用。
      • @Victor:捕获信号仅适用于可捕获信号。如果应用程序被 SIGKILLed 或 OOM-killed,或者如果它崩溃,捕获信号将无济于事。 (好吧,你可以抓到 SIGSEGV,但它很狡猾。你就是抓不到 SIGKILL。)
      • 好吧,没想到。再次感谢。
      【解决方案4】:

      有更好的方法可以防止应用程序运行两次。一种解决方案是使用系统范围的命名互斥体。另一种可能更简单的解决方案是锁定文件(打开以供写入)。即使应用程序崩溃资源被操作系统释放并且您将能够再次启动应用程序,因为文件或互斥体将不再被锁定。

      【讨论】:

        猜你喜欢
        • 2011-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        相关资源
        最近更新 更多