def _on_iface_is_up(self, event): """Network should be ready now, start DHCPv6 with subTLVs loaded from DB init file and from the system configuration files. :param event: unused :return: """ del event # Prepare "runtime" args - read suboption values from DB and append it # in expected format args = [] for code, attr in self.dhcp_args_mapping.iteritems(): if isinstance(attr, basestring): attr_val = attr else: attr_val = self.db_adapter.get_leaf(attr) if attr_val is None or type(attr_val) not in [ str, basestring, unicode ]: self.logger.debug("Attribute: %s not set in DB, ignoring ", attr) continue # append args in format: -x 0x0A:value args.extend(['-x', '{}:{}'.format(code, attr_val)]) args.append(self.INTF) self.processes['dhcpv6'].start(self.dhcp_msg_cb, args) # Re-enable signal blocking, which was disabled before forking sigprocmask(SIG_BLOCK, self.signal_mask, None) self.disp.loop()
def test_create_sigmask(self): from glibc import sigismember from signal import SIGABRT, SIGALRM, SIGHUP, getsignal from subprocess import PIPE siglist = [SIGINT, SIGQUIT, SIGTERM] default_handlers = {} mask = Manager.create_signal_mask() # Check if signals are in the mask & register callbacks for sig in siglist: self.assertTrue(sigismember(mask, sig)) default_handlers[sig] = getsignal(sig) signal(sig, self._sig_handler_fail) # A few examples of not expected signals for sig in [SIGABRT, SIGALRM, SIGHUP]: self.assertFalse(sigismember(mask, sig)) # Block signals in mask sigprocmask(SIG_BLOCK, mask, None) # Get line in format "SigBlk 00000000280b2603" from /proc/PID/status p1 = Popen(["grep", "SigBlk", "/proc/" + str(os.getpid()) + "/status"], stdout=PIPE, stderr=PIPE) p2 = Popen(["cut", "-f", "2"], stdin=p1.stdout, stdout=PIPE) p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. blocked_hex = p2.communicate()[0] blocked_bin = bin(int(blocked_hex, 16)) # These signals should be blocked for sig in siglist: os.kill(os.getpid(), SIGTERM) self.assertEqual(blocked_bin[-sig], '1') # Replace signal handler to drop pending signals for sig in siglist: signal(sig, self._sig_handler_ok) sigprocmask(SIG_UNBLOCK, mask, None) # Restore original signal handlers for sig in siglist: signal(sig, default_handlers[sig])
def main(): # Block signals so that they aren't handled # according to their default dispositions mask = sigset_t() fdsi = signalfd_siginfo() sigemptyset(mask) sigaddset(mask, SIGINT) sigaddset(mask, SIGQUIT) sigprocmask(SIG_BLOCK, mask, None) # Get a signalfd descriptor sfd = signalfd(-1, mask, SFD_CLOEXEC) # Get a epoll descriptor epollfd = epoll_create1(EPOLL_CLOEXEC) ev = epoll_event() ev.events = EPOLLIN ev.data.fd = sfd epoll_ctl(epollfd, EPOLL_CTL_ADD, sfd, byref(ev)) MAX_EVENTS = 10 events = (epoll_event * MAX_EVENTS)() with fdopen(sfd, 'rb', 0) as sfd_stream: while True: nfds = epoll_wait( epollfd, cast(byref(events), POINTER(epoll_event)), MAX_EVENTS, -1) for event_id in range(nfds): if events[event_id].data.fd == sfd: # Read the next delivered signal sfd_stream.readinto(fdsi) if fdsi.ssi_signo == SIGINT: print("Got SIGINT") elif fdsi.ssi_signo == SIGQUIT: print("Got SIGQUIT") return else: print("Read unexpected signal") else: raise Exception("unexpected fd?") close(sfd) close(epollfd)
def main(): # Block signals so that they aren't handled # according to their default dispositions mask = sigset_t() fdsi = signalfd_siginfo() sigemptyset(mask) sigaddset(mask, SIGINT) sigaddset(mask, SIGQUIT) sigprocmask(SIG_BLOCK, mask, None) # Get a signalfd descriptor sfd = signalfd(-1, mask, 0) with fdopen(sfd, 'rb', 0) as sfd_stream: while True: # Read the next delivered signal sfd_stream.readinto(fdsi) if fdsi.ssi_signo == SIGINT: print("Got SIGINT") elif fdsi.ssi_signo == SIGQUIT: print("Got SIGQUIT") return else: print("Read unexpected signal")
def main(): # Block signals so that they aren't handled # according to their default dispositions mask = sigset_t() fdsi = signalfd_siginfo() sigemptyset(mask) sigaddset(mask, SIGINT) sigaddset(mask, SIGQUIT) sigaddset(mask, SIGCHLD) sigaddset(mask, SIGPIPE) print("Blocking signals") sigprocmask(SIG_BLOCK, mask, None) # Get a signalfd descriptor sfd = signalfd(-1, mask, SFD_CLOEXEC | SFD_NONBLOCK) print("Got signalfd", sfd) # Get a epoll descriptor ep = epoll() print("Got epollfd", ep.fileno()) print("Adding signalfd fd {} to epoll".format(sfd)) ep.register(sfd, EPOLLIN) # Get two pair of pipes, one for stdout and one for stderr stdout_pair = (c_int * 2)() pipe2(byref(stdout_pair), O_CLOEXEC | O_NONBLOCK) print("Got stdout pipe pair", stdout_pair[0], stdout_pair[1]) print("Adding pipe fd {} to epoll".format(stdout_pair[0])) ep.register(stdout_pair[0], EPOLLIN) stderr_pair = (c_int * 2)() pipe2(byref(stderr_pair), O_CLOEXEC | O_NONBLOCK) print("Got stderr pipe pair", stderr_pair[0], stderr_pair[1]) print("Adding pipe fd {} to epoll".format(stdout_pair[0])) ep.register(stderr_pair[0], EPOLLIN) prog = argv[1:] if not prog: prog = ['echo', 'usage: demo.py PROG [ARGS]'] print("Going to start program:", prog) # Fork :-) pid = fork() if pid == 0: # Child. # NOTE: we are not closing any of the pipe ends. Why? Because they are # all O_CLOEXEC and will thus not live across the execlp call down # below. dup3(stdout_pair[1], 1, 0) dup3(stderr_pair[1], 2, 0) execlp(prog[0], *prog) return -1 else: close(stdout_pair[1]) close(stderr_pair[1]) with fdopen(sfd, 'rb', 0) as sfd_stream: waiting_for = set(['stdout', 'stderr', 'proc']) while waiting_for: print("Waiting for events...", ' '.join(waiting_for), flush=True) event_list = ep.poll(maxevents=10) print("epoll_wait() read {} events".format(len(event_list))) for fd, events in event_list: print("[event]") event_bits = [] if events & EPOLLIN == EPOLLIN: event_bits.append('EPOLLIN') if events & EPOLLOUT == EPOLLOUT: event_bits.append('EPOLLOUT') if events & EPOLLRDHUP == EPOLLRDHUP: event_bits.append('EPOLLRDHUP') if events & EPOLLPRI == EPOLLPRI: event_bits.append('EPOLLPRI') if events & EPOLLERR == EPOLLERR: event_bits.append('EPOLLERR') if events & EPOLLHUP == EPOLLHUP: event_bits.append('EPOLLHUP') if fd == sfd: fd_name = 'signalfd()' elif fd == stdout_pair[0]: fd_name = 'stdout pipe2()' elif fd == stderr_pair[0]: fd_name = 'stderr pipe2()' else: fd_name = "???" print(" events: {} ({})".format( events, ' | '.join(event_bits))) print(" fd: {} ({})".format(fd, fd_name)) if fd == sfd: print("signalfd() descriptor ready") if events & EPOLLIN: print("Reading data from signalfd()...") # Read the next delivered signal sfd_stream.readinto(fdsi) if fdsi.ssi_signo == SIGINT: print("Got SIGINT") elif fdsi.ssi_signo == SIGQUIT: print("Got SIGQUIT") raise SystemExit("exiting prematurly") elif fdsi.ssi_signo == SIGCHLD: print("Got SIGCHLD") waitid_result = waitid( P_PID, pid, WNOHANG | WEXITED | WSTOPPED | WCONTINUED | WUNTRACED) if waitid_result is None: print("child not ready") else: print("child event") print("si_pid:", waitid_result.si_pid) print("si_uid:", waitid_result.si_uid) print("si_signo:", waitid_result.si_signo) assert waitid_result.si_signo == SIGCHLD print("si_status:", waitid_result.si_status) print("si_code:", waitid_result.si_code) if waitid_result.si_code == CLD_EXITED: # assert WIFEXITED(waitid_result.si_status) print("child exited normally") print("exit code:", WEXITSTATUS(waitid_result.si_status)) waiting_for.remove('proc') if 'stdout' in waiting_for: ep.unregister(stdout_pair[0]) close(stdout_pair[0]) waiting_for.remove('stdout') if 'stderr' in waiting_for: ep.unregister(stderr_pair[0]) close(stderr_pair[0]) waiting_for.remove('stderr') elif waitid_result.si_code == CLD_KILLED: assert WIFSIGNALED(waitid_result.si_status) print("child was killed by signal") print("death signal:", waitid_result.si_status) waiting_for.remove('proc') elif waitid_result.si_code == CLD_DUMPED: assert WIFSIGNALED(waitid_result.si_status) print("core:", WCOREDUMP(waitid_result.si_status)) elif waitid_result.si_code == CLD_STOPPED: print("child was stopped") print("stop signal:", waitid_result.si_status) elif waitid_result.si_code == CLD_TRAPPED: print("child was trapped") # TODO: we could explore trap stuff here elif waitid_result.si_code == CLD_CONTINUED: print("child was continued") else: raise SystemExit( "Unknown CLD_ code: {}".format( waitid_result.si_code)) elif fdsi.ssi_signo == SIGPIPE: print("Got SIGPIPE") else: print("Read unexpected signal: {}".format( fdsi.ssi_signo)) elif fd == stdout_pair[0]: print("pipe() (stdout) descriptor ready") if events & EPOLLIN: print("Reading data from stdout...") data = read(stdout_pair[0], PIPE_BUF) print("Read {} bytes from stdout".format(len(data))) print(data) if events & EPOLLHUP: print("Removing stdout pipe from epoll") ep.unregister(stdout_pair[0]) print("Closing stdout pipe") close(stdout_pair[0]) waiting_for.remove('stdout') elif fd == stderr_pair[0]: print("pipe() (stderr) descriptor ready") if events & EPOLLIN: print("Reading data from stdout...") data = read(stderr_pair[0], PIPE_BUF) print("Read {} bytes from stderr".format(len(data))) print(data) if events & EPOLLHUP: print("Removing stderr pipe from epoll") ep.unregister(stderr_pair[0]) print("Closing stderr pipe") close(stderr_pair[0]) waiting_for.remove('stderr') else: # FIXME: we are still getting weird activation events on fd # 0 (stdin) with events == 0 (nothing). I cannot explain # this yet. print("Unexpected descriptor ready:", fd) assert not waiting_for print("Closing", ep) ep.close() print("Unblocking signals") sigprocmask(SIG_UNBLOCK, mask, None) print("Exiting normally")