0

I am using boost asio for my socket server application. Each connection is handled by a boost thread. I am using io_service per core, each io_service runs in a work thread.

In my connection I am using mysql C apis to query a database. When there is high traffic sometimes mysql_query/close api's do a SIGSEGV.

Is there a way to handle the SIGSEGV per thread so that my thread that calls mysql api which does a SIGSEGV, only handles the exception which other threads are unaffected.

this is the error I am getting Thread [17] 2844 [core: 0] (Suspended : Signal : SIGSEGV:Segmentation fault) 0x0 net_real_write() at 0x7ffff78d1ae5 net_flush() at 0x7ffff78d201b net_write_command() at 0x7ffff78d21d0 cli_advanced_command() at 0x7ffff78cf1ca mysql_send_query() at 0x7ffff78cd58d mysql_real_query() at 0x7ffff78cd5a9

1 Answers1

0

SIGSEGV is a synchronous signal. Thus, the thread in which SIGSEGV originates is the thread that will be targeted to handle SIGSEGV in its signal handler. This behavior is documented here:

certain signals, such as SIGSEGV and SIGFPE, generated as a consequence of executing a specific machine-language instruction are thread directed, as are signals targeted at a specific thread using pthread_kill

As far as I know, there is no way to exit a specific thread within a signal handler while maintaining defined behavior. To maintain defined behavior, only the following calls can be made from within the signal handler:

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()          execl()         execle()      execv()         execve()
faccessat()     fchmod()        fchmodat()    fchown()        fchownat()
fcntl()         fdatasync()     fexecve()     fork()          fstat()
fstatat()       fsync()         ftruncate()   futimens()      getegid()
geteuid()       getgid()        getgroups()   getpeername()   getpgrp()
getpid()        getppid()       getsockname() getsockopt()    getuid()
kill()          link()          linkat()      listen()        lseek()
lstat()         mkdir()         mkdirat()     mkfifo()        mkfifoat()
mknod()         mknodat()       open()        openat()        pause()
pipe()          poll()          posix_trace_event()           pselect()
raise()         read()          readlink()    readlinkat()    recv()
recvfrom()      recvmsg()       rename()      renameat()      rmdir()
select()        sem_post()      send()        sendmsg()       sendto()
setgid()        setpgid()       setsid()      setsockopt()    setuid()
shutdown()      sigaction()     sigaddset()   sigdelset()     sigemptyset()
sigfillset()    sigismember()   signal()      sigpause()      sigpending()
sigprocmask()   sigqueue()      sigset()      sigsuspend()    sleep()
sockatmark()    socket()        socketpair()  stat()          symlink()
symlinkat()     tcdrain()       tcflow()      tcflush()       tcgetattr()
tcgetpgrp()     tcsendbreak()   tcsetattr()   tcsetpgrp()     time()
timer_getoverrun()              timer_gettime()               timer_settime()
times()         umask()         uname()       unlink()        unlinkat()
utime()         utimensat()     utimes()      wait()          waitpid()
write()         _exit()         _Exit()

To get defined behavior, consider isolating the code that is causing SEGSEGV into its own process. For example, forking and using a process per connection would allow for SIGSEGV to only kill the process in which the error originates, without affecting other connections or introducing undefined behavior.

Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169