我需要 glibc 的异步信号安全函数列表

发布于 2024-08-16 14:32:16 字数 43 浏览 8 评论 0原文

非系统调用的包装器,但类似 ​​snprintf()、dprintf()

Non syscall's wrappers but something like snprintf(), dprintf()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

山有枢 2024-08-23 14:32:16

我很确定你必须看到文档

编辑

来自人信号

NOTES

   The effects of this call in a multi-threaded process are unspecified.


   The routine handler must be very careful,  since  processing  elsewhere
   was interrupted at some arbitrary point. POSIX has the concept of "safe
   function".  If a signal interrupts  an  unsafe  function,  and  handler
   calls  an  unsafe  function, then the behavior is undefined. Safe func-
   tions are listed explicitly in the various standards.  The POSIX.1-2003
   list is

   _Exit()  _exit()  abort()  accept()  access()  aio_error() aio_return()
   aio_suspend() alarm() bind() cfgetispeed() cfgetospeed()  cfsetispeed()
   cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect()
   creat() dup() dup2() execle() execve() fchmod() fchown() fcntl() fdata-
   sync()   fork()   fpathconf()  fstat()  fsync()  ftruncate()  getegid()
   geteuid() getgid() getgroups() getpeername() getpgrp()  getpid()  getp-
   pid()   getsockname()  getsockopt()  getuid()  kill()  link()  listen()
   lseek() lstat()  mkdir()  mkfifo()  open()  pathconf()  pause()  pipe()
   poll()  posix_trace_event()  pselect() raise() read() readlink() recv()
   recvfrom()  recvmsg()  rename()  rmdir()  select()  sem_post()   send()
   sendmsg()  sendto()  setgid()  setpgid() setsid() setsockopt() setuid()
   shutdown()  sigaction()  sigaddset()  sigdelset()  sigemptyset()   sig-
   fillset()  sigismember() signal() sigpause() sigpending() sigprocmask()
   sigqueue() sigset() sigsuspend() sleep() socket()  socketpair()  stat()
   symlink()  sysconf()  tcdrain()  tcflow() tcflush() tcgetattr() tcgetp-
   grp() tcsendbreak() tcsetattr() tcsetpgrp()  time()  timer_getoverrun()
   timer_gettime()   timer_settime()   times()  umask()  uname()  unlink()
   utime() wait() waitpid() write().

   According to POSIX, the behaviour of a process is  undefined  after  it
   ignores  a  SIGFPE, SIGILL, or SIGSEGV signal that was not generated by
   the kill(2) or the raise(3) functions.  Integer division  by  zero  has
   undefined result.  On some architectures it will generate a SIGFPE sig-
   nal.  (Also dividing the most  negative  integer  by  -1  may  generate
   SIGFPE.)  Ignoring this signal might lead to an endless loop.

   See  sigaction(2)  for  details  on what happens when SIGCHLD is set to
   SIG_IGN.

   The use of sighandler_t is a GNU extension.  Various versions  of  libc
   predefine  this  type;  libc4  and  libc5  define  SignalHandler, glibc
   defines sig_t and, when _GNU_SOURCE is defined, also sighandler_t.

I am pretty sure you have to see the documentation

Edit:
How about this list then?

From man signal:

NOTES

   The effects of this call in a multi-threaded process are unspecified.


   The routine handler must be very careful,  since  processing  elsewhere
   was interrupted at some arbitrary point. POSIX has the concept of "safe
   function".  If a signal interrupts  an  unsafe  function,  and  handler
   calls  an  unsafe  function, then the behavior is undefined. Safe func-
   tions are listed explicitly in the various standards.  The POSIX.1-2003
   list is

   _Exit()  _exit()  abort()  accept()  access()  aio_error() aio_return()
   aio_suspend() alarm() bind() cfgetispeed() cfgetospeed()  cfsetispeed()
   cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect()
   creat() dup() dup2() execle() execve() fchmod() fchown() fcntl() fdata-
   sync()   fork()   fpathconf()  fstat()  fsync()  ftruncate()  getegid()
   geteuid() getgid() getgroups() getpeername() getpgrp()  getpid()  getp-
   pid()   getsockname()  getsockopt()  getuid()  kill()  link()  listen()
   lseek() lstat()  mkdir()  mkfifo()  open()  pathconf()  pause()  pipe()
   poll()  posix_trace_event()  pselect() raise() read() readlink() recv()
   recvfrom()  recvmsg()  rename()  rmdir()  select()  sem_post()   send()
   sendmsg()  sendto()  setgid()  setpgid() setsid() setsockopt() setuid()
   shutdown()  sigaction()  sigaddset()  sigdelset()  sigemptyset()   sig-
   fillset()  sigismember() signal() sigpause() sigpending() sigprocmask()
   sigqueue() sigset() sigsuspend() sleep() socket()  socketpair()  stat()
   symlink()  sysconf()  tcdrain()  tcflow() tcflush() tcgetattr() tcgetp-
   grp() tcsendbreak() tcsetattr() tcsetpgrp()  time()  timer_getoverrun()
   timer_gettime()   timer_settime()   times()  umask()  uname()  unlink()
   utime() wait() waitpid() write().

   According to POSIX, the behaviour of a process is  undefined  after  it
   ignores  a  SIGFPE, SIGILL, or SIGSEGV signal that was not generated by
   the kill(2) or the raise(3) functions.  Integer division  by  zero  has
   undefined result.  On some architectures it will generate a SIGFPE sig-
   nal.  (Also dividing the most  negative  integer  by  -1  may  generate
   SIGFPE.)  Ignoring this signal might lead to an endless loop.

   See  sigaction(2)  for  details  on what happens when SIGCHLD is set to
   SIG_IGN.

   The use of sighandler_t is a GNU extension.  Various versions  of  libc
   predefine  this  type;  libc4  and  libc5  define  SignalHandler, glibc
   defines sig_t and, when _GNU_SOURCE is defined, also sighandler_t.
怀念你的温柔 2024-08-23 14:32:16

最后最新版本的 man 7 signal-safety 包含感兴趣的列表:signal-safety.7.html

Finally latest versions of man 7 signal-safety contain interested list: signal-safety.7.html

波浪屿的海角声 2024-08-23 14:32:16

这似乎很难确定,因为您不知道库例程可能决定调用什么随机不安全函数。该列表在不同版本的 glibc 之间也可能有所不同,或者如果您将其带到另一个类 Unix 系统中。似乎您必须分析大量调用堆栈才能找到答案,甚至从版本到版本、发行版到发行版,这可能有点不稳定。

也许您并不是在寻找替代的设计方法,但似乎更好的策略是:如果您的程序有事件循环,则使信号处理程序非常愚蠢,并仅设置事件循环将拾取的某些状态。这样您就可以在信号处理程序之外完成有意义的工作。

示例:假设您在某处有一个 poll() 循环。也许您可以包含信号处理程序可以写入的管道。然后,poll() 循环根据收到的信号执行一些重要的工作。

This seems hard to determine, as you don't know what random unsafe function a library routine might decide to call. The list also might different between different versions of glibc, or if you take it to another Unix-like system. Seems like you'd have to analyze a lot of call stacks to find the answer, and even that may be a bit shaky from version to version, distro to distro.

Maybe you are not looking for alternative design approaches, but it seems like a better strategy would be: if your program has an event loop, make the signal handler very stupid and just setting some state that the event loop will pick up. That way you do the meaningful work outside of the signal handler.

Example: Let's say you've got a poll() loop somewhere. Maybe you could include a pipe that the signal handler can write to. Then the poll() loop does some non-trivial work based on being signaled by that.

羁〃客ぐ 2024-08-23 14:32:16

应用程序崩溃后,我需要在 SIGSEGV 处理程序中使用它。

我想在崩溃时展开堆栈

如果您尝试捕获堆栈跟踪:

  • 通常中止会导致核心转储,可以通过调试器运行该核心转储以生成堆栈跟踪。

  • 或者,一种粗略的(但信号安全的)方法是forkexec一个单独的实用程序(例如“pstack”)来输出堆栈您崩溃的任务的踪迹。当 exec-ing 时(在 fork-ing 之后,在子进程中),您需要使用 getppid 传递进程 ID;在父级中,您需要等待它完成,然后再调用abort

另一方面,如果您尝试在 SIGSEGV 之后执行“干净”退出(例如,确保调用 C++ 析构函数等),则应该警告您 POSIX 会说:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_02 :

进程在忽略 SIGFPE 后的行为是未定义的,
不是由kill()生成的SIGILL、SIGSEGV或SIGBUS信号,
sigqueue() 或 raise()。

http://pubs.opengroup.org/onlinepubs/9699919799/functions /V2_chap02.html#tag_15_04_03_03

进程正常返回后的行为是未定义的
SIGBUS、SIGFPE、SIGILL 或 SIGSEGV 的信号捕获函数
信号不是由kill()、sigqueue() 或raise() 生成的。

I need this in SIGSEGV handler AFTER crash of application.

I want unwind stack on crash

If you're trying to capture a stack trace:

  • Typically abort would cause a core dump, which can be run through a debugger to produce the stack trace.

  • Alternatively, a crude (but signal-safe) way of doing so would be to fork and exec a separate utility (e.g. "pstack") to output a stack trace of your crashed task. When exec-ing (after fork-ing, in the child), you'll need to pass your process ID using getppid; and in the parent you'll need to wait for it to finish, before calling abort.

On the other hand, if you're trying to do a "clean" exit after SIGSEGV (e.g. ensuring C++ destructors get called, etc.) -- then you should be warned that POSIX says:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_02:

The behavior of a process is undefined after it ignores a SIGFPE,
SIGILL, SIGSEGV, or SIGBUS signal that was not generated by kill(),
sigqueue(), or raise().

and http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03:

The behavior of a process is undefined after it returns normally from
a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV
signal that was not generated by kill(), sigqueue(), or raise().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文