If open(2) fails with EMFILE or ENFILE, trigger a garbage collection
authorTaylor R. Campbell <net/mumble/campbell>
Wed, 15 Apr 2009 03:02:48 +0000 (03:02 +0000)
committerTaylor R. Campbell <net/mumble/campbell>
Wed, 15 Apr 2009 03:02:48 +0000 (03:02 +0000)
to attempt to free up file descriptors, but avoid looping in this
state if there really are too many open file descriptors still
referenced.

v7/src/microcode/uxfile.c

index 9b84135109b6bc18a7429c391ea09aef7d89ce4d..c7c81f206f2ec80c24b4aafadfc931bfddd90758 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: uxfile.c,v 1.18 2009/03/21 07:09:09 riastradh Exp $
+$Id: uxfile.c,v 1.19 2009/04/15 03:02:48 riastradh Exp $
 
 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
     1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
@@ -68,13 +68,35 @@ OS_open_fd (int fd)
     terminal_open (channel);
   return (channel);
 }
-
+\f
 static Tchannel
 open_file (const char * filename, int oflag)
 {
+  static bool out_of_files_p = false;
   int fd;
-  STD_UINT_SYSTEM_CALL
-    (syscall_open, fd, (UX_open (filename, oflag, MODE_REG)));
+  while ((fd = (UX_open (filename, oflag, MODE_REG))) < 0)
+    {
+      switch (errno)
+        {
+        case EINTR:
+          deliver_pending_interrupts ();
+          break;
+
+        case EMFILE:
+        case ENFILE:
+          if (!out_of_files_p)
+            {
+              out_of_files_p = true;
+              REQUEST_GC (0);
+              signal_interrupt_from_primitive ();
+            }
+          /* Fall through. */
+
+        default:
+          error_system_call (errno, syscall_open);
+        }
+    }
+  out_of_files_p = false;
 #ifdef SLAVE_PTY_P
   if ((SLAVE_PTY_P (filename)) && (!UX_setup_slave_pty (fd)))
     {