On Fri, 2005-04-01 at 20:19 +0200, Paul J Stevens wrote:
> Geo Carncross wrote:
> > On Thu, 2005-03-31 at 18:45 +0200, Paul J Stevens wrote:
> > 
> >>Geo Carncross wrote:
> >>
> >>>Be careful doing non-atomic things during signals. Since the signal will
> >>>likely have to write to a fifo anyway, it may be better to simply select
> >>>() on that fifo in the first-place...
> >>
> >>SELECT mtime FROM dbmail_mailboxes WHERE mailbox_idnr='%llu';
> >>
> >>seems pretty atomic to me. No need for fifos at all.
> > 
> > 
> > Not during a signal handler.
> > http://mirbsd.bsdadvocacy.org/cman/man2/sigaction.htm
> > 
> > The following functions are either reentrant or not interruptible by
> > signals and are async-signal safe.  Therefore applications may invoke
> > them, without restriction, from signal-catching functions:
> > 
> >      Base Interfaces:
> > 
> >      _exit(), access(), alarm(), cfgetispeed(), cfgetospeed(), 
> > cfsetispeed(),
> >      cfsetospeed(), chdir(), chmod(), chown(), close(), creat(), dup(),
> >      dup2(), execle(), execve(), fcntl(), fork(), fpathconf(), fstat(),
> >      fsync(), getegid(), geteuid(), getgid(), getgroups(), getpgrp(), get-
> >      pid(), getppid(), getuid(), kill(), link(), lseek(), mkdir(), mkfifo(),
> >      open(), pathconf(), pause(), pipe(), raise(), read(), rename(), 
> > rmdir(),
> >      setgid(), setpgid(), setsid(), setuid(), sigaction(), sigaddset(), sig-
> >      delset(), sigemptyset(), sigfillset(), sigismember(), signal(), 
> > sigpend-
> >      ing(), sigprocmask(), sigsuspend(), sleep(), stat(), sysconf(),
> >      tcdrain(), tcflow(), tcflush(), tcgetattr(), tcgetpgrp(), 
> > tcsendbreak(),
> >      tcsetattr(), tcsetpgrp(), time(), times(), umask(), uname(), unlink(),
> >      utime(), wait(), waitpid(), write().
> > 
> >      Realtime Interfaces:
> > 
> >      aio_error(), clock_gettime(), sigpause(), timer_getoverrun(),
> >      aio_return(), fdatasync(), sigqueue(), timer_gettime(), aio_suspend(),
> >      sem_post(), sigset(), timer_settime().
> > 
> > Unless we can be certain that the db backend won't do ANY SYSTEM CALL
> > except these, we need to wait until the signal handler is done. I know
> > for one, SQLite would need to use calls not here (notably: flock() and
> > mmap())
> 
> So what if? What is our worst case scenario here? Segfaults, corrupt database 
> tables on sqlite, off by one errors in our 'unsollicited responses', 
> generally 
> unpredictable behaviour, stack corruption?

Add denial-of-service attacks to that list.


> Or is this about being Thread-Safe[tm], which we aint anyways :-\

It's not. Thread-safety is a big joke that nobody is in on. What we mean
by reentrant here is that the kernel calls themselves are reentrant. It
means we can safely write to a pipe if the signal handler went off on a
select() that is blocking on that pipe.

Google "self pipe trick" (I'm so feeling lucky)


> That said, I will take to heart your point about atomic signal handlers. 
> There's 
> one section of the code in particular that has been bothering me; the zombies 
> in 
> caused by the process-pool code (pool.c). There, I use sigalarm to trigger 
> the 
> up/down scaling of idle processes which uses fnctl based locking. So I think 
> it's clean, but I not so sure anymore. Must investigate.

Self-pipe trick is the best way I know of to handle child processes when
using select()

-- 
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/

Reply via email to