
2013/11/7 Renato Forti
What do you think about self pipe built-in functionality? It is a widely used trick. I think it can be implemented as an aspect in a quite straightforward way.
Can you give more details about what you're proposing here? Elegant signal handler is my main problem in this lib! I want ideas to get it correctly designed!
The problem is to transfer interruption signal to the thread performing I/O multiplexing, for instance, waiting for new data during select(2) call. Default signal handler will force select(..) to return, but as far as we want to have a custom one, we need to abort select(..) manually. One can set a reasonable timeout for I/O operation, and check whether interruption signal have been delivered or not after timeout expires. For example, while (1) { if (termination_signal_received) { break; } // imagine signal received here, termination_signal_received set to true. // nevertheless, to get out of the loop we have to wait until timeout expires select(...); } This is a feasible solution, but it yields delayed termination and can not be accepted for some particular cases. The tricky solution is to set up an non-blocking pipe and add its read end to select(2)'s readfds array. Hence select(..) will return immediately when any data will be written to the pipe's write end. Therefore, write(selfpipe_write_fd, "", 1); must be called in signal handler after the termination_signal_received is set to true. The same effect can be achieved with signalfd(2). Unfortunately, this syscall is linux-specific. Here is a draft of the proposed aspect: class selfpipe : noncopyable { protected: void setup() { pipe(fd_); fcntl(fd_[READ_FD], F_SETFL, fcntl(fd_[READ_FD], F_GETFL) | O_NONBLOCK); fcntl(fd_[WRITE_FD], F_SETFL, fcntl(fd_[WRITE_FD], F_GETFL) | O_NONBLOCK); } void teardown() { close(fd_[READ_FD]; close(fd_[WRITE_FD]; } public: int readfd() const { return fd_[READ_FD]; } void poke() { write(fd_[WRITE_FD], "", 1); } private: enum { READ_FD = 0, WRITE_FD = 1 }; int fd_[2]; }; If an application has selfpipe aspect, the selfpipe::setup() method must be called during application's initialization, and selfpipe::teardown() during termination. -- Regards, Stas.