Report inotify instances limit error cidr/126.185 pycharm/126.187 rubymine/126.186 storm/126.183
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Fri, 8 Feb 2013 19:30:26 +0000 (20:30 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Fri, 8 Feb 2013 19:30:26 +0000 (20:30 +0100)
bin/linux/fsnotifier
bin/linux/fsnotifier64
native/fsNotifier/linux/fsnotifier.h
native/fsNotifier/linux/inotify.c
native/fsNotifier/linux/main.c
platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java

index df7985a5bfc2147a9c26006274ebecda1bf2cbf2..a34b7855db4f8fc3fa4bc66447e74a79d662202d 100755 (executable)
Binary files a/bin/linux/fsnotifier and b/bin/linux/fsnotifier differ
index 9f0b3a46d2f2488c8b375be26b8227112ad4274d..812e326cd6a1136a4e233e1d3890dc7e1d94cd9a 100755 (executable)
Binary files a/bin/linux/fsnotifier64 and b/bin/linux/fsnotifier64 differ
index 0b3e52705513c25c251987e9c1b061276ecbf86e..0140d6be81022b6da66cb0534f223df1a21e0baf 100644 (file)
 #include <stdio.h>
 
 
+// messaging
+typedef enum {
+  MSG_INSTANCE_LIMIT, MSG_WATCH_LIMIT
+} MSG;
+
+void message(MSG id);
+
+
 // logging
 void userlog(int priority, const char* format, ...);
 
@@ -59,8 +67,6 @@ enum {
 bool init_inotify();
 void set_inotify_callback(void (* callback)(char*, int));
 int get_inotify_fd();
-int get_watch_count();
-bool watch_limit_reached();
 int watch(const char* root, array* mounts);
 void unwatch(int id);
 bool process_inotify_input();
index 75a97abc13397cf5162f92c58747c65b5cee1f15..8570d032e78294e0d750d7e641727be316e57f31 100644 (file)
@@ -49,30 +49,18 @@ static void (* callback)(char*, int) = NULL;
 #define EVENT_BUF_LEN (2048 * (EVENT_SIZE + 16))
 static char event_buf[EVENT_BUF_LEN];
 
-
-static void read_watch_descriptors_count() {
-  FILE* f = fopen(WATCH_COUNT_NAME, "r");
-  if (f == NULL) {
-    userlog(LOG_ERR, "can't open %s: %s", WATCH_COUNT_NAME, strerror(errno));
-    return;
-  }
-
-  char* str = read_line(f);
-  if (str == NULL) {
-    userlog(LOG_ERR, "can't read from %s", WATCH_COUNT_NAME);
-  }
-  else {
-    watch_count = atoi(str);
-  }
-
-  fclose(f);
-}
+static void read_watch_descriptors_count();
+static void watch_limit_reached();
 
 
 bool init_inotify() {
   inotify_fd = inotify_init();
   if (inotify_fd < 0) {
-    userlog(LOG_ERR, "inotify_init: %s", strerror(errno));
+    int e = errno;
+    userlog(LOG_ERR, "inotify_init: %s", strerror(e));
+    if (e == EMFILE) {
+      message(MSG_INSTANCE_LIMIT);
+    }
     return false;
   }
   userlog(LOG_DEBUG, "inotify fd: %d", get_inotify_fd());
@@ -96,24 +84,32 @@ bool init_inotify() {
   return true;
 }
 
+static void read_watch_descriptors_count() {
+  FILE* f = fopen(WATCH_COUNT_NAME, "r");
+  if (f == NULL) {
+    userlog(LOG_ERR, "can't open %s: %s", WATCH_COUNT_NAME, strerror(errno));
+    return;
+  }
 
-inline void set_inotify_callback(void (* _callback)(char*, int)) {
-  callback = _callback;
-}
-
+  char* str = read_line(f);
+  if (str == NULL) {
+    userlog(LOG_ERR, "can't read from %s", WATCH_COUNT_NAME);
+  }
+  else {
+    watch_count = atoi(str);
+  }
 
-inline int get_inotify_fd() {
-  return inotify_fd;
+  fclose(f);
 }
 
 
-inline int get_watch_count() {
-  return watch_count;
+inline void set_inotify_callback(void (* _callback)(char*, int)) {
+  callback = _callback;
 }
 
 
-inline bool watch_limit_reached() {
-  return limit_reached;
+inline int get_inotify_fd() {
+  return inotify_fd;
 }
 
 
@@ -128,7 +124,7 @@ static int add_watch(const char* path, watch_node* parent) {
     }
     else if (errno == ENOSPC) {
       userlog(LOG_WARNING, "inotify_add_watch(%s): %s", path, strerror(errno));
-      limit_reached = true;
+      watch_limit_reached();
       return ERR_CONTINUE;
     }
     else {
@@ -188,6 +184,12 @@ static int add_watch(const char* path, watch_node* parent) {
   return wd;
 }
 
+static void watch_limit_reached() {
+  if (!limit_reached) {
+    limit_reached = true;
+    message(MSG_WATCH_LIMIT);
+  }
+}
 
 static void rm_watch(int wd, bool update_parent) {
   watch_node* node = table_get(watches, wd);
index 87fcf26139b90871d0d99bd8715b0fafde1568b9..27372e35acc109da02ac20630fc97cb3980ede2e 100644 (file)
 #define HELP_MSG \
     "Try 'fsnotifier --help' for more information.\n"
 
-#define INOTIFY_LIMIT_MSG \
-    "The current <b>inotify</b>(7) watch limit of %d is too low. " \
+#define INSTANCE_LIMIT_TEXT \
+    "The <b>inotify</b>(7) instances limit reached. " \
+    "<a href=\"http://confluence.jetbrains.net/display/IDEADEV/Inotify+Instances+Limit\">More details.</a>\n"
+
+#define WATCH_LIMIT_TEXT \
+    "The current <b>inotify</b>(7) watch limit is too low. " \
     "<a href=\"http://confluence.jetbrains.net/display/IDEADEV/Inotify+Watches+Limit\">More details.</a>\n"
 
 typedef struct {
@@ -59,7 +63,6 @@ typedef struct {
 
 static array* roots = NULL;
 
-static bool show_warning = true;
 static bool self_test = false;
 
 static void init_log();
@@ -152,6 +155,19 @@ static void init_log() {
 }
 
 
+void message(MSG id) {
+  if (id == MSG_INSTANCE_LIMIT) {
+    output("MESSAGE\n" INSTANCE_LIMIT_TEXT);
+  }
+  else if (id == MSG_WATCH_LIMIT) {
+    output("MESSAGE\n" WATCH_LIMIT_TEXT);
+  }
+  else {
+    userlog(LOG_ERR, "unknown message: %d", id);
+  }
+}
+
+
 void userlog(int priority, const char* format, ...) {
   va_list ap;
 
@@ -353,12 +369,6 @@ static bool register_roots(array* new_roots, array* unwatchable, array* mounts)
       return false;
     }
     else if (id != ERR_IGNORE) {
-      if (show_warning && watch_limit_reached()) {
-        int limit = get_watch_count();
-        userlog(LOG_WARNING, "watch limit (%d) reached", limit);
-        output("MESSAGE\n" INOTIFY_LIMIT_MSG, limit);
-        show_warning = false;  // warn only once
-      }
       CHECK_NULL(array_push(unwatchable, strdup(unflattened)), false);
     }
   }
index 631b7d0b3d10ad1ce2898ec2aa4d2418142f1ab5..20ee724be7261409a66cbfde2a2fac27347513d9 100644 (file)
@@ -173,7 +173,7 @@ public class FileWatcher {
   private static boolean isUpToDate(File executable) {
     long length = SystemInfo.isWindows ? 70216 :
                   SystemInfo.isMac ? 13924 :
-                  SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29308 : 22809 :
+                  SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29227 : 22734 :
                   -1;
     return length < 0 || length == executable.length();
   }