2012-02-09 6 views
7

मेरे पास कोड का एक साधारण टुकड़ा है जो समय-समय पर उस एफडी को डेटा लिखता है जो इसे पारित किया जाता है। एफडी सबसे अधिक संभावना है कि एक पाइप या सॉकेट हो लेकिन संभावित रूप से कुछ भी हो सकता है। जब भी मैं लिखता हूं() को सॉकेट/पाइप बंद/टूटा हुआ है, तो मुझे पता चल सकता है, क्योंकि मुझे एक ईपीआईपीई त्रुटि मिलती है (मैं सिगिप को अनदेखा कर रहा हूं)। लेकिन मैं इसे हर समय नहीं लिखता, और इसलिए लंबे समय तक बंद सॉकेट का पता नहीं लगा सकता है। मुझे बंद करने के लिए बंद करने की जरूरत है। क्या लिखने के बिना एफडी की जांच करने की कोई विधि है()? अगर मैं कुछ भी नहीं लिख रहा हूं तो मैं समय-समय पर ऐसा कर सकता हूं।लिनक्स: एक सॉकेट/पाइप को पढ़ने के बिना तोड़ दिया जाता है()/लिखना()

का चयन और उसके errorfds पैरामीटर के साथ
+2

का चयन करें, सर्वेक्षण, और epoll तुम सब –

+0

जवाब के लिए धन्यवाद बता देंगे, लेकिन मुझे यकीन है कि के साथ इस काम करने के लिए कैसे नहीं कर रहा हूँ पाइप। मैंने लिखने और fdsets को छोड़कर मेरे एफडी के साथ एक चुनिंदा() कॉल करने का प्रयास किया है, और जब पाइप टूटा हुआ है तो कॉल का नतीजा तब नहीं बदलता है (हमेशा लिखने के सेट में अपना एफडी वापस कर दें)। मैंने सभी घटनाओं के साथ मतदान() भी कोशिश की है और फिर कोई फर्क नहीं पड़ता। – gimmeamilk

+0

अपने एफडी को लिखने वाले fdsets में धक्का न दें। केवल एक को छोड़कर। –

उत्तर

8
struct pollfd pfd = {.fd = yourfd, .events = POLLERR}; 
if (poll(&pfd, 1, whatever) < 0) abort(); 
if (pfd.revents & POLLERR) printf("pipe is broken\n"); 

यह मेरे लिए काम करता है। ध्यान दें कि सॉकेट बिल्कुल पाइप नहीं होते हैं और इस प्रकार विभिन्न व्यवहार दिखाते हैं (-> पोलरड्रूप का उपयोग करें)।

+0

आह! मेरे पास एक टाइपो था और पुनरुत्थान के बजाए रास्ते पर घटनाओं की जांच कर रहा था। बहुत धन्यवाद, यह बहुत अच्छा काम किया। – gimmeamilk

+1

ग्रेट उत्तर। मैं चुनने के लिए बहुत अधिक आदी हूं() कॉल। मुझे निश्चित रूप से उस बिंदु पर विकसित करने की कोशिश करनी चाहिए। +1 –

2

प्रयास करें:

int **select**(int nfds, fd_set *restrict readfds, 
     fd_set *restrict writefds, **fd_set *restrict errorfds**, 
     struct timeval *restrict timeout); 
+1

धन्यवाद, लेकिन मैंने अपवाद सेट में अपना एफडी जोड़ने की कोशिश की और पाइप टूटने पर इसे अलग तरीके से व्यवहार नहीं कर सका। (यह सॉकेट के साथ ठीक काम कर सकता है; मैंने अभी तक कोशिश नहीं की है क्योंकि मेरा वर्तमान सेटअप मुझे पाइप देता है) – gimmeamilk

1

अच्छा जवाब, मुझे उन्हें पसंद है ... मुझे चुनिंदा खरगोश और (ई) सर्वेक्षण में भी बाहर निकलना होगा।

/* check whether a file-descriptor is valid */ 
int fd_valid(int fd) 
{ 
    if (fcntl(fd, F_GETFL) == -1 && errno == EBADF) return FALSE; 
    return TRUE; 
}  

यह एक सॉकेट/fd नकल करने का प्रयास:

यहाँ कुछ अधिक परंपरागत तरीकों अगर तुम उन्हें जरूरत है,। यह दिखता है की तुलना में बहुत आसान है, मैं में डिबग का एक बहुत छोड़ दिया है।

/* check a file descriptor */ 
int fd_check(int i) { 
    int fd_dup = dup(i); 
    if (fd_dup == -1) { 
     strcpy(errst, strerror(errno)); 
     // EBADF oldfd isn’t an open file descriptor, or newfd is out of the allowed range for file descriptors. 
     // EBUSY (Linux only) This may be returned by dup2() during a race condition with open(2) and dup(). 
     // EINTR The dup2() call was interrupted by a signal; see signal(7). 
     // EMFILE The process already has the maximum number of file descriptors open and tried to open a new one. 

     if (errno == EBADF) { 
      return FALSE; 
     } 

     return TRUE; 
    } 
    close(fd_dup); 
    return TRUE; 
}