【问题标题】:Setting environment variable for a running program in linux在linux中为正在运行的程序设置环境变量
【发布时间】:2015-06-23 18:57:40
【问题描述】:

我的程序使用环境变量DBG_MSG 值来确定调试消息的级别。 DBG_MSG=3 打印最大调试信息。

但是,当程序以一种奇怪的意外方式运行时,环境变量并未设置为打印完整的调试信息。并且当程序在环境设置下重新运行时,它不会显示相同的错误。

我正在考虑为SIGUSR1 实现一个信号处理程序,以便在运行时使用putenv(3) 设置此环境变量。这样我就可以将信号发送到挂起的作业以使其打印更多调试信息。

这样做时需要采取哪些安全措施?

有没有其他方法可以从外部改变正在运行的程序的环境?

【问题讨论】:

  • 我很困惑。可能其他人也会。
  • 问题是,当你打印调试信息时,这个 bug 就消失了,这意味着你的程序调用了未定义的行为,所以调试器会有很大帮助,像 valgrind 这样的内存调试器会更有帮助,而且发布有问题的代码将对可能帮助您的人有所帮助。
  • @iharob 你说的是真的,除了这更有可能是导致死锁的竞争条件而不是内存损坏问题(所以,helgrind 可能而不是 valgrind)和描述让我觉得我们在谈论一个非常庞大、复杂的网络守护程序,即使发布一个精简版也不实用。

标签: c linux environment-variables signals


【解决方案1】:

putenv 不是async-signal-safe,因此应该从不SIGUSR1 处理程序中调用。此外,putenv 所做的更改不一定会被另一个线程中的getenv 调用注意到。

您应该做的是在启动时仅读取一次DBG_MSG 环境变量,并将值存储在类型为volatile sig_atomic_t 的全局变量中。您的调试日志例程应该查看这个变量来决定要打印多少信息。然后让信号处理程序调整变量的值。

我还建议SIGUSR1 应该增加变量,SIGUSR2 应该减少它。这样您就可以根据需要提高和降低日志级别。

sig_atomic_t 可能非常小,并且不能保证是有符号或无符号的:可移植程序只能使用它来存储 0 到 127 (含)范围内的值。因此,请确保您的信号处理程序将该值限制在对您的程序有意义的范围内(也就是说,不要将日志级别增加到超过最大值或将其降低到超过最小值)。

【讨论】:

    【解决方案2】:

    安全措施是:不要这样做。

    putenv(3) 不是异步信号安全的(主要是因为它可以调用malloc(3)),因此您不应该真正从信号处理程序中调用它。

    【讨论】:

    • gdb调用任意函数也不安全;事实上,根据你闯入程序的位置,它可能与从异步信号处理程序调用它们一样完全有风险。
    • @zwol 哦,我不知道。那很有意思。谢谢你让我知道!我将更新我的答案。
    • 我知道这个 hack 并已在开发中使用它。但我正在寻找一种更用户友好的方式来做到这一点。用户可以根据需要激活的东西。
    • 这样想:异步信号处理程序必须非常小心它们所做的事情,因为它们可能会中断程序任何部分的执行(除非信号被阻塞),包括库的内部功能。好吧,调试器闯入比这更具侵入性:它甚至可以中断一个所有可阻塞信号都被阻塞的程序。所以在回调到程序中的时候需要更加谨慎。 (当然,驱动调试器的人可以检查调用堆栈并决定什么是安全的。)
    【解决方案3】:

    您需要确保您不会在程序中遇到环境变量。环境变量应该从你的 shell 中设置一次,不要管它。 .. 毕竟,它们是环境变量。他们只是为您的程序设置或定义环境。

    【讨论】:

      【解决方案4】:

      还有一种方法.... 你也可以实现 ioctl 调用..

      甚至很多司机都在做同样的事情..

      【讨论】:

      • 您能详细说明一下吗?
      猜你喜欢
      • 2015-08-07
      • 2015-02-14
      • 1970-01-01
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      相关资源
      最近更新 更多