~pythonregexp2.7/python/issue2636-01+09-02

« back to all changes in this revision

Viewing changes to Lib/asyncore.py

  • Committer: Jeffrey C. "The TimeHorse" Jacobs
  • Date: 2008-09-22 00:16:16 UTC
  • mfrom: (39022.1.34 Regexp-2.7)
  • Revision ID: darklord@timehorse.com-20080922001616-p1wdip9lfp0zl5cu
Merged in changes from the Atomic Grouping / Possessive Qualifiers branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 
54
54
import os
55
55
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
56
 
     ENOTCONN, ESHUTDOWN, EINTR, EISCONN, errorcode
 
56
     ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED, errorcode
57
57
 
58
58
try:
59
59
    socket_map
60
60
except NameError:
61
61
    socket_map = {}
62
62
 
 
63
def _strerror(err):
 
64
    res = os.strerror(err)
 
65
    if res == 'Unknown error':
 
66
        res = errorcode[err]
 
67
    return res
 
68
 
63
69
class ExitNow(Exception):
64
70
    pass
65
71
 
66
72
def read(obj):
67
73
    try:
68
74
        obj.handle_read_event()
69
 
    except ExitNow:
 
75
    except (ExitNow, KeyboardInterrupt, SystemExit):
70
76
        raise
71
77
    except:
72
78
        obj.handle_error()
74
80
def write(obj):
75
81
    try:
76
82
        obj.handle_write_event()
77
 
    except ExitNow:
 
83
    except (ExitNow, KeyboardInterrupt, SystemExit):
78
84
        raise
79
85
    except:
80
86
        obj.handle_error()
81
87
 
82
 
def _exception (obj):
 
88
def _exception(obj):
83
89
    try:
84
90
        obj.handle_expt_event()
85
 
    except ExitNow:
 
91
    except (ExitNow, KeyboardInterrupt, SystemExit):
86
92
        raise
87
93
    except:
88
94
        obj.handle_error()
93
99
            obj.handle_read_event()
94
100
        if flags & select.POLLOUT:
95
101
            obj.handle_write_event()
96
 
        if flags & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
 
102
        if flags & (select.POLLERR | select.POLLNVAL):
97
103
            obj.handle_expt_event()
98
 
    except ExitNow:
 
104
        if flags & select.POLLHUP:
 
105
            obj.handle_close()
 
106
    except (ExitNow, KeyboardInterrupt, SystemExit):
99
107
        raise
100
108
    except:
101
109
        obj.handle_error()
116
124
                e.append(fd)
117
125
        if [] == r == w == e:
118
126
            time.sleep(timeout)
119
 
        else:
120
 
            try:
121
 
                r, w, e = select.select(r, w, e, timeout)
122
 
            except select.error, err:
123
 
                if err[0] != EINTR:
124
 
                    raise
125
 
                else:
126
 
                    return
 
127
            return
 
128
 
 
129
        try:
 
130
            r, w, e = select.select(r, w, e, timeout)
 
131
        except select.error, err:
 
132
            if err.args[0] != EINTR:
 
133
                raise
 
134
            else:
 
135
                return
127
136
 
128
137
        for fd in r:
129
138
            obj = map.get(fd)
166
175
        try:
167
176
            r = pollster.poll(timeout)
168
177
        except select.error, err:
169
 
            if err[0] != EINTR:
 
178
            if err.args[0] != EINTR:
170
179
                raise
171
180
            r = []
172
181
        for fd, flags in r:
209
218
        else:
210
219
            self._map = map
211
220
 
 
221
        self._fileno = None
 
222
 
212
223
        if sock:
 
224
            # Set to nonblocking just to make sure for cases where we
 
225
            # get a socket from a blocking source.
 
226
            sock.setblocking(0)
213
227
            self.set_socket(sock, map)
214
 
            # I think it should inherit this anyway
215
 
            self.socket.setblocking(0)
216
228
            self.connected = True
217
 
            # XXX Does the constructor require that the socket passed
218
 
            # be connected?
 
229
            # The constructor no longer requires that the socket
 
230
            # passed be connected.
219
231
            try:
220
232
                self.addr = sock.getpeername()
221
 
            except socket.error:
222
 
                # The addr isn't crucial
223
 
                pass
 
233
            except socket.error, err:
 
234
                if err.args[0] == ENOTCONN:
 
235
                    # To handle the case where we got an unconnected
 
236
                    # socket.
 
237
                    self.connected = False
 
238
                else:
 
239
                    # The socket is broken in some unknown way, alert
 
240
                    # the user and remove it from the map (to prevent
 
241
                    # polling of broken sockets).
 
242
                    self.del_channel(map)
 
243
                    raise
224
244
        else:
225
245
            self.socket = None
226
246
 
247
267
        fd = self._fileno
248
268
        if map is None:
249
269
            map = self._map
250
 
        if map.has_key(fd):
 
270
        if fd in map:
251
271
            #self.log_info('closing channel %d:%s' % (fd, self))
252
272
            del map[fd]
253
273
        self._fileno = None
254
274
 
255
275
    def create_socket(self, family, type):
256
276
        self.family_and_type = family, type
257
 
        self.socket = socket.socket(family, type)
258
 
        self.socket.setblocking(0)
259
 
        self._fileno = self.socket.fileno()
260
 
        self.add_channel()
 
277
        sock = socket.socket(family, type)
 
278
        sock.setblocking(0)
 
279
        self.set_socket(sock)
261
280
 
262
281
    def set_socket(self, sock, map=None):
263
282
        self.socket = sock
295
314
    def listen(self, num):
296
315
        self.accepting = True
297
316
        if os.name == 'nt' and num > 5:
298
 
            num = 1
 
317
            num = 5
299
318
        return self.socket.listen(num)
300
319
 
301
320
    def bind(self, addr):
310
329
            return
311
330
        if err in (0, EISCONN):
312
331
            self.addr = address
313
 
            self.connected = True
314
 
            self.handle_connect()
 
332
            self.handle_connect_event()
315
333
        else:
316
 
            raise socket.error, (err, errorcode[err])
 
334
            raise socket.error(err, errorcode[err])
317
335
 
318
336
    def accept(self):
319
337
        # XXX can return either an address pair or None
321
339
            conn, addr = self.socket.accept()
322
340
            return conn, addr
323
341
        except socket.error, why:
324
 
            if why[0] == EWOULDBLOCK:
 
342
            if why.args[0] == EWOULDBLOCK:
325
343
                pass
326
344
            else:
327
345
                raise
331
349
            result = self.socket.send(data)
332
350
            return result
333
351
        except socket.error, why:
334
 
            if why[0] == EWOULDBLOCK:
 
352
            if why.args[0] == EWOULDBLOCK:
 
353
                return 0
 
354
            elif why.args[0] in (ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED):
 
355
                self.handle_close()
335
356
                return 0
336
357
            else:
337
358
                raise
338
 
            return 0
339
359
 
340
360
    def recv(self, buffer_size):
341
361
        try:
349
369
                return data
350
370
        except socket.error, why:
351
371
            # winsock sometimes throws ENOTCONN
352
 
            if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
 
372
            if why.args[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED]:
353
373
                self.handle_close()
354
374
                return ''
355
375
            else:
356
376
                raise
357
377
 
358
378
    def close(self):
 
379
        self.connected = False
 
380
        self.accepting = False
359
381
        self.del_channel()
360
 
        self.socket.close()
 
382
        try:
 
383
            self.socket.close()
 
384
        except socket.error, why:
 
385
            if why.args[0] not in (ENOTCONN, EBADF):
 
386
                raise
361
387
 
362
388
    # cheap inheritance, used to pass all other attribute
363
389
    # references to the underlying socket object.
377
403
 
378
404
    def handle_read_event(self):
379
405
        if self.accepting:
380
 
            # for an accepting socket, getting a read implies
381
 
            # that we are connected
382
 
            if not self.connected:
383
 
                self.connected = True
 
406
            # accepting sockets are never connected, they "spawn" new
 
407
            # sockets that are connected
384
408
            self.handle_accept()
385
409
        elif not self.connected:
386
 
            self.handle_connect()
387
 
            self.connected = True
 
410
            self.handle_connect_event()
388
411
            self.handle_read()
389
412
        else:
390
413
            self.handle_read()
391
414
 
 
415
    def handle_connect_event(self):
 
416
        self.connected = True
 
417
        self.handle_connect()
 
418
 
392
419
    def handle_write_event(self):
393
 
        # getting a write implies that we are connected
 
420
        if self.accepting:
 
421
            # Accepting sockets shouldn't get a write event.
 
422
            # We will pretend it didn't happen.
 
423
            return
 
424
 
394
425
        if not self.connected:
395
 
            self.handle_connect()
396
 
            self.connected = True
 
426
            #check for errors
 
427
            err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
 
428
            if err != 0:
 
429
                raise socket.error(err, _strerror(err))
 
430
 
 
431
            self.handle_connect_event()
397
432
        self.handle_write()
398
433
 
399
434
    def handle_expt_event(self):
400
 
        self.handle_expt()
 
435
        # if the handle_expt is the same default worthless method,
 
436
        # we'll not even bother calling it, we'll instead generate
 
437
        # a useful error
 
438
        x = True
 
439
        try:
 
440
            y1 = self.__class__.handle_expt.im_func
 
441
            y2 = dispatcher.handle_expt.im_func
 
442
            x = y1 is y2
 
443
        except AttributeError:
 
444
            pass
 
445
 
 
446
        if x:
 
447
            err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
 
448
            msg = _strerror(err)
 
449
 
 
450
            raise socket.error(err, msg)
 
451
        else:
 
452
            self.handle_expt()
401
453
 
402
454
    def handle_error(self):
403
455
        nil, t, v, tbinfo = compact_traceback()
417
469
                ),
418
470
            'error'
419
471
            )
420
 
        self.close()
 
472
        self.handle_close()
421
473
 
422
474
    def handle_expt(self):
423
475
        self.log_info('unhandled exception', 'warning')
473
525
def compact_traceback():
474
526
    t, v, tb = sys.exc_info()
475
527
    tbinfo = []
476
 
    assert tb # Must have a traceback
 
528
    if not tb: # Must have a traceback
 
529
        raise AssertionError("traceback does not exist")
477
530
    while tb:
478
531
        tbinfo.append((
479
532
            tb.tb_frame.f_code.co_filename,
489
542
    info = ' '.join(['[%s|%s|%s]' % x for x in tbinfo])
490
543
    return (file, function, line), t, v, info
491
544
 
492
 
def close_all(map=None):
 
545
def close_all(map=None, ignore_all=False):
493
546
    if map is None:
494
547
        map = socket_map
495
548
    for x in map.values():
496
 
        x.socket.close()
 
549
        try:
 
550
            x.close()
 
551
        except OSError, x:
 
552
            if x.args[0] == EBADF:
 
553
                pass
 
554
            elif not ignore_all:
 
555
                raise
 
556
        except (ExitNow, KeyboardInterrupt, SystemExit):
 
557
            raise
 
558
        except:
 
559
            if not ignore_all:
 
560
                raise
497
561
    map.clear()
498
562
 
499
563
# Asynchronous File I/O:
513
577
    import fcntl
514
578
 
515
579
    class file_wrapper:
516
 
        # here we override just enough to make a file
 
580
        # Here we override just enough to make a file
517
581
        # look like a socket for the purposes of asyncore.
 
582
        # The passed fd is automatically os.dup()'d
518
583
 
519
584
        def __init__(self, fd):
520
 
            self.fd = fd
 
585
            self.fd = os.dup(fd)
521
586
 
522
587
        def recv(self, *args):
523
588
            return os.read(self.fd, *args)
539
604
        def __init__(self, fd, map=None):
540
605
            dispatcher.__init__(self, None, map)
541
606
            self.connected = True
 
607
            try:
 
608
                fd = fd.fileno()
 
609
            except AttributeError:
 
610
                pass
542
611
            self.set_file(fd)
543
612
            # set it to non-blocking mode
544
613
            flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)