[gamin] Inotify patch and crash fix
- From: John McCutchan <ttb tentacle dhs org>
- To: gamin-list gnome org
- Subject: [gamin] Inotify patch and crash fix
- Date: Tue, 12 Jul 2005 13:51:46 -0400
Yo,
Attached is a patch that updates gamin to the new inotify interface.
Because of pressure in the kernel world, we have switched from a char
device to a set of system calls. Changes are minimal, but they are not
API compatible.
The patch includes the removal of 1 assert in gam_node.c. This assert
was causing crashes for me everytime the gtk+ file selector was brought
up.
--
John McCutchan <ttb tentacle dhs org>
Index: server/gam_inotify.c
===================================================================
RCS file: /cvs/gnome/gamin/server/gam_inotify.c,v
retrieving revision 1.24
diff -u -r1.24 gam_inotify.c
--- server/gam_inotify.c 13 Jun 2005 09:13:45 -0000 1.24
+++ server/gam_inotify.c 12 Jul 2005 17:47:50 -0000
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdio.h>
+#include <string.h>
#include <glib.h>
#include "gam_error.h"
#include "gam_poll.h"
@@ -44,15 +45,22 @@
#include "gam_debugging.h"
#endif
+#include <errno.h>
+
+#define INOTIFY_INIT 291
+#define INOTIFY_ADD 292
+#define INOTIFY_RM 293
+
typedef struct {
char *path;
int wd;
int refcount;
- GList *subs;
int busy;
gboolean deactivated;
+ gboolean ignored;
int events;
int deactivated_events;
+ int ignored_events;
} inotify_data_t;
static GHashTable *path_hash = NULL;
@@ -77,8 +85,9 @@
return;
int deactivated = data->deactivated;
+ int ignored = data->ignored;
- GAM_DEBUG(DEBUG_INFO, "isub wd %d refs %d busy %d deactivated %d events (%d:%d): %s\n", data->wd, data->refcount, data->busy, deactivated, data->events, data->deactivated_events, data->path);
+ GAM_DEBUG(DEBUG_INFO, "isub wd %d refs %d busy %d deactivated %d ignored %d events (%d:%d:%d): %s\n", data->wd, data->refcount, data->busy, deactivated, ignored, data->events, data->deactivated_events, data->ignored_events, data->path);
}
void
@@ -163,13 +172,18 @@
{
inotify_data_t *data;
+ g_assert (wd >= 0);
+
data = g_new0(inotify_data_t, 1);
data->path = g_strdup(path);
data->wd = wd;
- data->busy = 0;
data->refcount = 1;
- data->deactivated_events = 0;
+ data->busy = 0;
+ data->deactivated = FALSE;
+ data->ignored = FALSE;
data->events = 0;
+ data->deactivated_events = 0;
+ data->ignored_events = 0;
return data;
}
@@ -187,8 +201,7 @@
gam_inotify_directory_handler_internal(const char *path, pollHandlerMode mode)
{
inotify_data_t *data;
- int path_fd, path_wd;
- struct inotify_watch_request iwr;
+ int path_wd = -1;
switch (mode) {
case GAMIN_ACTIVATE:
GAM_DEBUG(DEBUG_INFO, "Adding %s to inotify\n", path);
@@ -211,7 +224,6 @@
G_LOCK(inotify);
if (mode == GAMIN_ACTIVATE) {
-
if ((data = g_hash_table_lookup(path_hash, path)) != NULL) {
data->refcount++;
GAM_DEBUG(DEBUG_INFO, " found incremented refcount: %d\n",
@@ -224,17 +236,15 @@
return;
}
- path_fd = open(path, O_RDONLY);
+ path_wd = syscall (INOTIFY_ADD, inotify_device_fd, path, should_poll_mask);
- if (path_fd < 0) {
- G_UNLOCK(inotify);
- return;
- }
-
- iwr.fd = path_fd;
- iwr.mask = should_poll_mask;
- path_wd = ioctl (inotify_device_fd, INOTIFY_WATCH, &iwr);
- close (path_fd);
+ if (path_wd < 0) {
+ int e = errno;
+ GAM_DEBUG(DEBUG_INFO, "INOTIFY_ADD failed for %s\n", path);
+ GAM_DEBUG(DEBUG_INFO, "Error = %s\n", strerror(e));
+ G_UNLOCK(inotify);
+ return;
+ }
data = gam_inotify_data_new(path, path_wd);
g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd), data);
@@ -260,17 +270,31 @@
if (data->refcount == 0) {
int wd = data->wd;
+ g_assert (data->wd >= 0);
GAM_DEBUG(DEBUG_INFO, "removed inotify watch for %s\n",
data->path);
g_hash_table_remove(path_hash, data->path);
g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
- gam_inotify_data_free(data);
- if (ioctl (inotify_device_fd, INOTIFY_IGNORE, &wd) < 0) {
- GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
+
+ if (data->ignored) {
+ GAM_DEBUG(DEBUG_INFO, "INOTIFY_IGNORE IGNORED for %s (wd = %d)\n", data->path, data->wd);
+ }
+ if (data->deactivated == FALSE) {
+ if (syscall (INOTIFY_RM, inotify_device_fd, wd) < 0) {
+ int e = errno;
+ GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
+
+ GAM_DEBUG(DEBUG_INFO, "reason = %s\n", strerror (e));
+ } else {
+ GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE success for %s (wd = %d)\n", data->path, data->wd);
+ }
+ } else {
+ GAM_DEBUG (DEBUG_INFO, "removed deactivated inotify watch for %s\n", data->path);
}
#ifdef GAMIN_DEBUG_API
gam_debug_report(GAMinotifyDelete, data->path, 0);
#endif
+ gam_inotify_data_free(data);
} else {
GAM_DEBUG(DEBUG_INFO, " found decremented refcount: %d\n",
data->refcount);
@@ -283,16 +307,19 @@
data = g_hash_table_lookup(path_hash, path);
if (!data) {
GAM_DEBUG(DEBUG_INFO, " not found !!!\n");
-
G_UNLOCK(inotify);
return;
}
if (data != NULL) {
if (mode == GAMIN_FLOWCONTROLSTART) {
GAM_DEBUG(DEBUG_INFO, "inotify: GAMIN_FLOWCONTROLSTART for %s\n", data->path);
- if (data->wd >= 0) {
- if (ioctl (inotify_device_fd, INOTIFY_IGNORE, &data->wd) < 0) {
+ if (!data->deactivated) {
+ if (syscall (INOTIFY_RM, inotify_device_fd, data->wd) < 0) {
+ int e = errno;
GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd);
+ GAM_DEBUG(DEBUG_INFO, "reason = %s\n", strerror (e));
+ } else {
+ GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE success for %s (wd = %d)\n", data->path, data->wd);
}
data->deactivated = TRUE;
GAM_DEBUG(DEBUG_INFO, "deactivated inotify for %s\n",
@@ -300,6 +327,8 @@
#ifdef GAMIN_DEBUG_API
gam_debug_report(GAMinotifyFlowOn, data->path, 0);
#endif
+ } else {
+ GAM_DEBUG(DEBUG_INFO, "inotify: GAMIN_FLOWCONTROLSTART for %s -- AGAIN!!!!\n", data->path);
}
data->busy++;
} else {
@@ -309,24 +338,24 @@
data->busy--;
if (data->busy == 0) {
GAM_DEBUG(DEBUG_INFO, "inotify: data->busy == 0 for %s\n", data->path);
- path_fd = open(data->path, O_RDONLY);
- if (path_fd < 0) {
+
+ path_wd = syscall (INOTIFY_ADD, inotify_device_fd, data->path, should_poll_mask);
+
+ if (path_wd < 0) {
+ int e = errno;
G_UNLOCK(inotify);
GAM_DEBUG(DEBUG_INFO,
"failed to reactivate inotify for %s\n",
data->path);
+ GAM_DEBUG(DEBUG_INFO, "reason = %s\n", strerror (e));
return;
}
-
- iwr.fd = path_fd;
- iwr.mask = should_poll_mask;
- path_wd = ioctl (inotify_device_fd, INOTIFY_WATCH, &iwr);
- close (path_fd);
+ g_assert (data->wd >= 0);
+ g_assert (path_wd >= 0);
/* Remove the old wd from the hash table */
g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd));
-
data->wd = path_wd;
data->deactivated = FALSE;
@@ -419,21 +448,13 @@
} else if (data->deactivated) {
GAM_DEBUG(DEBUG_INFO, "inotify: ignoring event on temporarily deactivated watch %s\n", data->path);
data->deactivated_events++;
- } else {
+ } else if (data->ignored) {
+ GAM_DEBUG(DEBUG_INFO, "inotify: got event on ignored watch %s\n", data->path);
+ } else {
if (event->mask == IN_IGNORED) {
- GList *l;
-
GAM_DEBUG(DEBUG_INFO, "inotify: IN_IGNORE on wd=%d\n", event->wd);
- GAM_DEBUG(DEBUG_INFO, "inotify: removing all subscriptions for %s\n", data->path);
-
- data->events++;
-
- l = data->subs;
- data->subs = NULL;
- for (l = l; l; l = l->next) {
- GamSubscription *sub = l->data;
- gam_inotify_remove_subscription (sub);
- }
+ data->ignored = TRUE;
+ data->ignored_events++;
} else if (event->mask != IN_Q_OVERFLOW) {
if (event->mask & should_poll_mask) {
GAM_DEBUG(DEBUG_INFO, "inotify requesting poll for %s\n", data->path);
@@ -513,10 +534,11 @@
g_return_val_if_fail(gam_poll_init_full(FALSE), FALSE);
- inotify_device_fd = open("/dev/inotify", O_RDONLY);
+ inotify_device_fd = syscall(INOTIFY_INIT);
if (inotify_device_fd < 0) {
GAM_DEBUG(DEBUG_INFO, "Could not open /dev/inotify\n");
+ GAM_DEBUG(DEBUG_INFO, "fd = %d\n", inotify_device_fd);
return FALSE;
}
Index: server/gam_node.c
===================================================================
RCS file: /cvs/gnome/gamin/server/gam_node.c,v
retrieving revision 1.12
diff -u -r1.12 gam_node.c
--- server/gam_node.c 13 Jun 2005 14:58:07 -0000 1.12
+++ server/gam_node.c 12 Jul 2005 17:47:50 -0000
@@ -189,7 +189,9 @@
gam_node_remove_subscription(GamNode * node, GamSubscription * sub)
{
g_assert(node);
- g_assert(g_list_find(node->subs, sub));
+
+ if (!g_list_find (node->subs, sub))
+ return TRUE;
node->subs = g_list_remove_all(node->subs, sub);
Index: server/local_inotify.h
===================================================================
RCS file: /cvs/gnome/gamin/server/local_inotify.h,v
retrieving revision 1.8
diff -u -r1.8 local_inotify.h
--- server/local_inotify.h 10 May 2005 09:29:52 -0000 1.8
+++ server/local_inotify.h 12 Jul 2005 17:47:50 -0000
@@ -23,16 +23,6 @@
char name[0]; /* stub for possible name */
};
-/*
- * struct inotify_watch_request - represents a watch request
- *
- * Pass to the inotify device via the INOTIFY_WATCH ioctl
- */
-struct inotify_watch_request {
- int fd; /* fd of filename to watch */
- __u32 mask; /* event mask */
-};
-
/* the following are legal, implemented events that user-space can watch for */
#define IN_ACCESS 0x00000001 /* File was accessed */
#define IN_MODIFY 0x00000002 /* File was modified */
@@ -68,12 +58,6 @@
IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
-#define INOTIFY_IOCTL_MAGIC 'Q'
-#define INOTIFY_IOCTL_MAXNR 2
-
-#define INOTIFY_WATCH _IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request)
-#define INOTIFY_IGNORE _IOR(INOTIFY_IOCTL_MAGIC, 2, int)
-
#ifdef __KERNEL__
#include <linux/dcache.h>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]