Hello,

Here's a patch for handling EBADF (Bad file descriptor) error after select()
(following the thread "random abort caused by ecore").

It uses fcntl() for finding which fd raises EBADF. I tested the patch with
the attached program (somehow dirty but maybe shows the patch works).

Please mail me with any suggestions.

-- 
André Dieb Martins

Embedded Systems and Pervasive Computing Lab (Embedded)
Electrical Engineering Department (DEE)
Center of Electrical Engineering and Informatics (CEEI)
Federal University of Campina Grande (UFCG)

Blog: http://genuinepulse.blogspot.com/
Mail: dieb at embedded.ufcg.edu.br, andre.dieb at gmail.com
Index: src/lib/ecore/ecore_main.c
===================================================================
--- src/lib/ecore/ecore_main.c	(revision 39915)
+++ src/lib/ecore/ecore_main.c	(working copy)
@@ -18,6 +18,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <errno.h>
+#include <fcntl.h>
 
 #define FIX_HZ 1
 
@@ -33,6 +34,7 @@
 
 static int  _ecore_main_select(double timeout);
 static void _ecore_main_fd_handlers_cleanup(void);
+static void _ecore_main_fd_handlers_bads_rem(void);
 static void _ecore_main_fd_handlers_call(void);
 static int  _ecore_main_fd_handlers_buf_call(void);
 static void _ecore_main_loop_iterate_internal(int once_only);
@@ -354,11 +356,14 @@
 	  }
      }
    if (_ecore_signal_count_get()) return -1;
+
    ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);
    _ecore_loop_time = ecore_time_get();
    if (ret < 0)
      {
 	if (errno == EINTR) return -1;
+	else if (errno == EBADF)
+	     _ecore_main_fd_handlers_bads_rem();
      }
    if (ret > 0)
      {
@@ -379,6 +384,45 @@
 }
 
 static void
+_ecore_main_fd_handlers_bads_rem(void)
+{
+   fprintf(stderr, "Removing bad fds\n");
+   Ecore_Fd_Handler *fdh;
+   Eina_Inlist *l;
+
+   for (l = EINA_INLIST_GET(fd_handlers); l; )
+     {
+	fdh = (Ecore_Fd_Handler *) l;
+	l = l->next;
+	errno = 0;
+
+	if ((fcntl(fdh->fd, F_GETFD) < 0) && (errno == EBADF))
+	  {
+	     fprintf(stderr, "Found bad fd at index %d\n", fdh->fd);
+	     if (fdh->flags & ECORE_FD_ERROR)
+	       {
+		  fprintf(stderr, "Fd set for error! calling user\n");
+	         if (!fdh->func(fdh->data, fdh))
+		   {
+		     fprintf(stderr, "Fd function err returned 0, remove it\n");
+		     fdh->delete_me = 1;
+		     fd_handlers_delete_me = 1;
+		     _ecore_main_fd_handlers_cleanup();
+		   }
+	       }
+	     else
+	       {
+		  fprintf(stderr, "Problematic fd found at %d! setting it for delete\n", fdh->fd);
+		  fdh->delete_me = 1;
+		  fd_handlers_delete_me = 1;
+		  _ecore_main_fd_handlers_cleanup();
+	       }
+	  }
+
+    }
+}
+
+static void
 _ecore_main_fd_handlers_cleanup(void)
 {
    Ecore_Fd_Handler *fdh;
@@ -392,6 +436,7 @@
 	l = l->next;
 	if (fdh->delete_me)
 	  {
+	     fprintf(stderr, "Removing fd %d\n", fdh->fd);
 	     fd_handlers = (Ecore_Fd_Handler *) eina_inlist_remove(EINA_INLIST_GET(fd_handlers),
 								   EINA_INLIST_GET(fdh));
 	     ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
#include <Ecore.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>

int myfunc(void *data, Ecore_Fd_Handler *fdh) {
    char *d;
    d = (char *) data;
    fprintf(stderr, "Myfunc! %s\n", d);
    return 0;
}

int main(void) {
    int fd[2];
    ecore_init();
    pipe(fd);
    ecore_main_fd_handler_add(fd[0], ECORE_FD_READ, myfunc, "hi", NULL, NULL);
    ecore_main_fd_handler_add(fd[1], ECORE_FD_WRITE, myfunc, "hello", NULL, NULL);
    write(fd[1], "hello", strlen("hello")+1);
    close(fd[1]);
    close(fd[0]);
    ecore_main_loop_begin();
    return 0;
}
------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to