diff --git a/bin/linux/fsnotifier b/bin/linux/fsnotifier index df7985a5bfc2..a34b7855db4f 100755 Binary files a/bin/linux/fsnotifier and b/bin/linux/fsnotifier differ diff --git a/bin/linux/fsnotifier64 b/bin/linux/fsnotifier64 index 9f0b3a46d2f2..812e326cd6a1 100755 Binary files a/bin/linux/fsnotifier64 and b/bin/linux/fsnotifier64 differ diff --git a/native/fsNotifier/linux/fsnotifier.h b/native/fsNotifier/linux/fsnotifier.h index 0b3e52705513..0140d6be8102 100644 --- a/native/fsNotifier/linux/fsnotifier.h +++ b/native/fsNotifier/linux/fsnotifier.h @@ -21,6 +21,14 @@ #include +// 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(); diff --git a/native/fsNotifier/linux/inotify.c b/native/fsNotifier/linux/inotify.c index 75a97abc1339..8570d032e782 100644 --- a/native/fsNotifier/linux/inotify.c +++ b/native/fsNotifier/linux/inotify.c @@ -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,6 +84,24 @@ 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; + } + + 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); +} + inline void set_inotify_callback(void (* _callback)(char*, int)) { callback = _callback; @@ -107,16 +113,6 @@ inline int get_inotify_fd() { } -inline int get_watch_count() { - return watch_count; -} - - -inline bool watch_limit_reached() { - return limit_reached; -} - - #define EVENT_MASK IN_MODIFY | IN_ATTRIB | IN_CREATE | IN_DELETE | IN_MOVE | IN_DELETE_SELF static int add_watch(const char* path, watch_node* parent) { @@ -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); diff --git a/native/fsNotifier/linux/main.c b/native/fsNotifier/linux/main.c index 87fcf26139b9..27372e35acc1 100644 --- a/native/fsNotifier/linux/main.c +++ b/native/fsNotifier/linux/main.c @@ -48,8 +48,12 @@ #define HELP_MSG \ "Try 'fsnotifier --help' for more information.\n" -#define INOTIFY_LIMIT_MSG \ - "The current inotify(7) watch limit of %d is too low. " \ +#define INSTANCE_LIMIT_TEXT \ + "The inotify(7) instances limit reached. " \ + "More details.\n" + +#define WATCH_LIMIT_TEXT \ + "The current inotify(7) watch limit is too low. " \ "More details.\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); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index 631b7d0b3d10..20ee724be726 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -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(); }