OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.test.test_fdesc -*- | |
2 | |
3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
4 # See LICENSE for details. | |
5 | |
6 | |
7 """ | |
8 Utility functions for dealing with POSIX file descriptors. | |
9 """ | |
10 | |
11 import sys | |
12 import os | |
13 import errno | |
14 import fcntl | |
15 if (sys.hexversion >> 16) >= 0x202: | |
16 FCNTL = fcntl | |
17 else: | |
18 import FCNTL | |
19 | |
20 # twisted imports | |
21 from twisted.internet.main import CONNECTION_LOST, CONNECTION_DONE | |
22 | |
23 | |
24 def setNonBlocking(fd): | |
25 """ | |
26 Make a file descriptor non-blocking. | |
27 """ | |
28 flags = fcntl.fcntl(fd, FCNTL.F_GETFL) | |
29 flags = flags | os.O_NONBLOCK | |
30 fcntl.fcntl(fd, FCNTL.F_SETFL, flags) | |
31 | |
32 | |
33 def setBlocking(fd): | |
34 """ | |
35 Make a file descriptor blocking. | |
36 """ | |
37 flags = fcntl.fcntl(fd, FCNTL.F_GETFL) | |
38 flags = flags & ~os.O_NONBLOCK | |
39 fcntl.fcntl(fd, FCNTL.F_SETFL, flags) | |
40 | |
41 | |
42 def readFromFD(fd, callback): | |
43 """ | |
44 Read from file descriptor, calling callback with resulting data. | |
45 | |
46 Returns same thing FileDescriptor.doRead would. | |
47 | |
48 @type fd: C{int} | |
49 @param fd: non-blocking file descriptor to be read from. | |
50 @param callback: a callable which accepts a single argument. If | |
51 data is read from the file descriptor it will be called with this | |
52 data. Handling exceptions from calling the callback is up to the | |
53 caller. | |
54 | |
55 Note that if the descriptor is still connected but no data is read, | |
56 None will be returned but callback will not be called. | |
57 | |
58 @return: CONNECTION_LOST on error, CONNECTION_DONE when fd is | |
59 closed, otherwise None. | |
60 """ | |
61 try: | |
62 output = os.read(fd, 8192) | |
63 except (OSError, IOError), ioe: | |
64 if ioe.args[0] in (errno.EAGAIN, errno.EINTR): | |
65 return | |
66 else: | |
67 return CONNECTION_LOST | |
68 if not output: | |
69 return CONNECTION_DONE | |
70 callback(output) | |
71 | |
72 def writeToFD(fd, data): | |
73 """ | |
74 Write data to file descriptor. | |
75 | |
76 Returns same thing FileDescriptor.writeSomeData would. | |
77 | |
78 @type fd: C{int} | |
79 @param fd: non-blocking file descriptor to be written to. | |
80 @type data: C{str} or C{buffer} | |
81 @param data: bytes to write to fd. | |
82 | |
83 @return: number of bytes written, or CONNECTION_LOST. | |
84 """ | |
85 try: | |
86 return os.write(fd, data) | |
87 except (OSError, IOError), io: | |
88 if io.errno in (errno.EAGAIN, errno.EINTR): | |
89 return 0 | |
90 return CONNECTION_LOST | |
91 | |
92 | |
93 __all__ = ["setNonBlocking", "setBlocking", "readFromFD", "writeToFD"] | |
OLD | NEW |