2008-12-10 40 views
11

(Tôi đang sử dụng các mô-đun pyprocessing trong ví dụ này, nhưng thay thế chế biến với đa có lẽ nên làm việc nếu bạn chạy python 2.6 hoặc sử dụng multiprocessing backport)Đúng cách hủy chấp nhận và đóng một kết nối Python/xử lý đa Listener

Tôi hiện đang có một chương trình lắng nghe một unix socket (sử dụng một processing.connection.Listener), chấp nhận các kết nối và sinh ra một thread xử lý yêu cầu. Tại một thời điểm nhất định, tôi muốn thoát khỏi quá trình một cách duyên dáng, nhưng vì cuộc gọi accept() đang chặn và tôi không thấy cách nào để hủy bỏ nó một cách tốt đẹp. Tôi có một cách mà làm việc ở đây (OS X) ít nhất, thiết lập một xử lý tín hiệu và tín hiệu quá trình này từ thread khác như vậy:

import processing 
from processing.connection import Listener 
import threading 
import time 
import os 
import signal 
import socket 
import errno 

# This is actually called by the connection handler. 
def closeme(): 
    time.sleep(1) 
    print 'Closing socket...' 
    listener.close() 
    os.kill(processing.currentProcess().getPid(), signal.SIGPIPE) 

oldsig = signal.signal(signal.SIGPIPE, lambda s, f: None) 

listener = Listener('/tmp/asdf', 'AF_UNIX') 
# This is a thread that handles one already accepted connection, left out for brevity 
threading.Thread(target=closeme).start() 
print 'Accepting...' 
try: 
    listener.accept() 
except socket.error, e: 
    if e.args[0] != errno.EINTR: 
     raise 
# Cleanup here... 
print 'Done...' 

Cách duy nhất khác mà tôi đã nghĩ đến việc là tiếp cận sâu vào kết nối (listener._listener._socket) và thiết lập tùy chọn không chặn ... nhưng điều đó có thể có một số tác dụng phụ và thường thực sự đáng sợ.

Có ai có cách thanh lịch hơn (và thậm chí có thể chính xác!) Để hoàn thành việc này không? Nó cần phải được di động với OS X, Linux và BSD, nhưng tính di động của Windows vv là không cần thiết.

Làm rõ: Cảm ơn tất cả mọi người! Như thường lệ, sự mơ hồ trong câu hỏi ban đầu của tôi được tiết lộ :)

  • Tôi cần thực hiện dọn dẹp sau khi tôi đã hủy nghe và tôi không muốn thực sự thoát khỏi quá trình đó.
  • tôi cần để có thể truy cập vào quá trình này từ các quá trình khác không sinh ra từ cùng một mẹ, mà làm cho Queues trở nên cồng kềnh
  • Những lý do cho đề là rằng:
    • Họ truy cập vào một trạng thái chia sẻ. Trên thực tế nhiều hơn hoặc ít hơn một cơ sở dữ liệu trong bộ nhớ phổ biến, vì vậy tôi cho rằng nó có thể được thực hiện khác nhau.
    • Tôi phải có thể có nhiều kết nối được chấp nhận cùng một lúc, nhưng các chuỗi thực tế đang chặn phần lớn thời gian. Mỗi kết nối được chấp nhận sinh ra một luồng mới; điều này để không chặn tất cả các máy khách trên các dịch vụ I/O.

đề vs quá trình Về, tôi sử dụng chủ đề cho việc chặn ops tôi non-blocking và quy trình để cho phép đa xử lý.

Trả lời

3

Đó không phải là lựa chọn gì?

Chỉ gọi chấp nhận trên socket nếu chọn cho thấy nó sẽ không chặn ...

Các lựa chọn có một thời gian chờ, vì vậy bạn có thể thoát ra khỏi Thỉnh thoảng Thỉnh thoảng kiểm tra nếu thời gian của mình để đóng cửa ... .

+0

Không phải là một ý tưởng tồi cho mỗi se, nhưng đối tượng Listener không phơi bày các ổ cắm cơ bản, và tôi không muốn vi phạm pháp luật demeters trong một cách lớn như vậy. Khi nó quay ra, tuy nhiên đó là chính xác những gì tôi phải làm :) –

0

Có lẽ không lý tưởng, nhưng bạn có thể giải phóng khối bằng cách gửi ổ cắm một số dữ liệu từ bộ xử lý tín hiệu hoặc chuỗi đang kết thúc quá trình.

EDIT: Một cách khác để thực hiện việc này có thể là sử dụng Kết nối Queues, vì chúng dường như hỗ trợ hết giờ (xin lỗi, tôi đã đọc mã của bạn trong lần đọc đầu tiên).

+0

Vì nó không nhận được hoạt động Tôi đang cố gắng hủy bỏ Tôi thực sự không thể gửi dữ liệu đến kết nối (không có) và có cũng là một điều kiện chủng tộc ở đó. Thứ hai, điều đó sẽ hiệu quả nếu tôi thực sự đang bỏ phiếu cho dữ liệu, tôi không; Tôi đang chờ kết nối mới. Hay tôi hiểu lầm bạn? –

+0

Vì Trình nghe đang chấp nhận các kết nối trên ổ cắm được chỉ định, không nên kết nối với nó từ một bản phát hành luồng khác chấp nhận() (sử dụng multiprocessing.connection.Client)? Xin lỗi vì sự mơ hồ trong phần thứ hai của câu trả lời của tôi, tôi sẽ sửa nó. – codelogic

+0

Hàng đợi không thể phát hiện được từ các công cụ bên ngoài vv. Kết nối với ổ cắm sẽ giải phóng accepy(), nhưng sẽ tạo ra một cuộc đua, tôi nghĩ vậy. –

1

Tôi mới sử dụng mô-đun đa xử lý, nhưng có vẻ như tôi trộn lẫn mô-đun xử lý và mô-đun luồng là phản trực giác, họ có nhắm mục tiêu giải quyết cùng một vấn đề không?

Dù sao, làm cách nào để gói các chức năng nghe của bạn thành một quy trình? Tôi không rõ điều này ảnh hưởng đến phần còn lại của mã của bạn như thế nào, nhưng điều này có thể là một giải pháp thay thế sạch hơn.

from multiprocessing import Process 
from multiprocessing.connection import Listener 


class ListenForConn(Process): 

    def run(self): 
     listener = Listener('/tmp/asdf', 'AF_UNIX') 
     listener.accept() 

     # do your other handling here 


listen_process = ListenForConn() 
listen_process.start() 

print listen_process.is_alive() 

listen_process.terminate() 
listen_process.join() 

print listen_process.is_alive() 
print 'No more listen process.' 
+0

Đó là nhiều hơn hoặc ít hơn những gì tôi làm, nhưng bạn gửi SIGTERM thay vì SIGPIPE, và bạn không thể làm sạch trong bối cảnh run(), mà là trong một trình xử lý tín hiệu. –

+0

Cảm ơn bạn đã làm rõ, không có gì đến với tâm trí tại thời điểm này, nếu tôi nghĩ về một cái gì đó tôi sẽ cập nhật câu trả lời của tôi. ;) – monkut

+0

Alright, nỗ lực tốt đẹp mặc dù :) –

3

tôi nghĩ tôi có thể tránh nó, nhưng có vẻ như tôi phải làm một cái gì đó như thế này:

from processing import connection 
connection.Listener.fileno = lambda self: self._listener._socket.fileno() 

import select 

l = connection.Listener('/tmp/x', 'AF_UNIX') 
r, w, e = select.select((l,),(),()) 
if l in r: 
    print "Accepting..." 
    c = l.accept() 
    # ... 

tôi biết rằng điều này vi phạm pháp luật của Demeter và giới thiệu một số ác khỉ vá, nhưng nó có vẻ như đây sẽ là ea nhất cách hoàn thành việc này. Nếu bất cứ ai có một giải pháp thanh lịch hơn, tôi sẽ rất vui khi nghe nó :)

Các vấn đề liên quan