def test(self): # pylint:disable=too-many-locals # If this test is broken, there are a few failure modes. # - In the original examples, the parent process just hangs, because the # child has raced ahead, spawned the greenlet and read the data. When the # greenlet goes to read in the parent, it blocks, and the hub and loop # wait for it. # - Here, our child detects the greenlet ran when it shouldn't and # raises an error, which translates to a non-zero exit status, # which the parent checks for and fails by raising an exception before # returning control to the hub. We can replicate the hang by removing the # assertion in the child. from time import sleep as hang from gevent import get_hub from gevent import spawn from gevent.socket import wait_read from gevent.os import nb_read from gevent.os import nb_write from gevent.os import make_nonblocking from gevent.os import fork from gevent.os import waitpid pipe_read_fd, pipe_write_fd = os.pipe() make_nonblocking(pipe_read_fd) make_nonblocking(pipe_write_fd) run = [] def reader(): run.append(1) return nb_read(pipe_read_fd, 4096) # Put data in the pipe DATA = b'test' nb_write(pipe_write_fd, DATA) # Make sure we're ready to read it wait_read(pipe_read_fd) # Schedule a greenlet to start reader = spawn(reader) hub = get_hub() pid = fork() if pid == 0: # Child destroys the hub. The reader should not have run. hub.destroy(destroy_loop=True) self.assertFalse(run) os._exit(0) return # The parent. # Briefly prevent us from spinning our event loop. hang(0.5) wait_child_result = waitpid(pid, 0) self.assertEqual(wait_child_result, (pid, 0)) # We should get the data; the greenlet only runs in the parent. data = reader.get() self.assertEqual(run, [1]) self.assertEqual(data, DATA)
def non_blocking_write(file_obj, input_buffer): if not input_buffer: return try: from gevent.os import nb_write nb_write(file_obj.fileno(), input_buffer) except ImportError: return retry_loop_on_eagain(file_obj.write, input_buffer)
def write_unsigned(fd, n): msg = UNSIGNED_STRUCT.pack(n) while msg: nbytes = nb_write(fd, msg) if nbytes == 0: raise RuntimeError('should not get here') msg = msg[nbytes:]
def _send(self, cmd, name): self.ensure_running() msg = '{0}:{1}\n'.format(cmd, name).encode('ascii') if len(name) > 512: # posix guarantees that writes to a pipe of less than PIPE_BUF # bytes are atomic, and that PIPE_BUF >= 512 raise ValueError('name too long') nbytes = nb_write(self._fd, msg) assert nbytes == len(msg)
def write(self, *args): return os.nb_write(*args)
def write(self, fd, count): return os.nb_write(fd, count)