Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crashes reported for 271ef97 #22

Closed
dmatveev opened this issue Mar 7, 2015 · 10 comments
Closed

Crashes reported for 271ef97 #22

dmatveev opened this issue Mar 7, 2015 · 10 comments

Comments

@dmatveev
Copy link
Owner

dmatveev commented Mar 7, 2015

The following program crashes with the recent changes in libinotify, though it works fine on GNU/Linux:

/* compile: "cc inotify.c -o inotify -linotify -I/usr/local/include -L/usr/local/lib" */
/* run: "./inotify ." */

#include <sys/inotify.h>
#include <limits.h>
#include <err.h>
#include <stdio.h>
#include <sys/types.h>  /* Type definitions used by many programs */
#include <stdio.h>      /* Standard I/O functions */
#include <stdlib.h>     /* Prototypes of commonly used library functions,
               plus EXIT_SUCCESS and EXIT_FAILURE constants */
#include <unistd.h>     /* Prototypes for many system calls */
#include <errno.h>      /* Declares errno and defines error constants */
#include <string.h>     /* Commonly used string-handling functions */

static void             /* Display information from inotify_event structure */
displayInotifyEvent(struct inotify_event *i)
{
    printf("    wd =%2d; ", i->wd);
    if (i->cookie > 0)
        printf("cookie =%4d; ", i->cookie);

    printf("mask = ");
    if (i->mask & IN_ACCESS)        printf("IN_ACCESS ");
    if (i->mask & IN_ATTRIB)        printf("IN_ATTRIB ");
    if (i->mask & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE ");
    if (i->mask & IN_CLOSE_WRITE)   printf("IN_CLOSE_WRITE ");
    if (i->mask & IN_CREATE)        printf("IN_CREATE ");
    if (i->mask & IN_DELETE)        printf("IN_DELETE ");
    if (i->mask & IN_DELETE_SELF)   printf("IN_DELETE_SELF ");
    if (i->mask & IN_IGNORED)       printf("IN_IGNORED ");
    if (i->mask & IN_ISDIR)         printf("IN_ISDIR ");
    if (i->mask & IN_MODIFY)        printf("IN_MODIFY ");
    if (i->mask & IN_MOVE_SELF)     printf("IN_MOVE_SELF ");
    if (i->mask & IN_MOVED_FROM)    printf("IN_MOVED_FROM ");
    if (i->mask & IN_MOVED_TO)      printf("IN_MOVED_TO ");
    if (i->mask & IN_OPEN)          printf("IN_OPEN ");
    if (i->mask & IN_Q_OVERFLOW)    printf("IN_Q_OVERFLOW ");
    if (i->mask & IN_UNMOUNT)       printf("IN_UNMOUNT ");
    printf("\n");

    if (i->len > 0)
        printf("        name = %s\n", i->name);
}

#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))

int
main(int argc, char *argv[])
{
    int inotifyFd, wd, j;
    char buf[BUF_LEN] __attribute__ ((aligned(8)));
    ssize_t numRead;
    char *p;
    struct inotify_event *event;

    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        printf("%s pathname...\n", argv[0]);

    inotifyFd = inotify_init();                 /* Create inotify instance */
    if (inotifyFd == -1)
        perror("inotify_init");

   /* For each command-line argument, add a watch for all events */

    for (j = 1; j < argc; j++) {
        wd = inotify_add_watch(inotifyFd, argv[j], (IN_MODIFY | IN_ATTRIB |
            IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF));
        if (wd == -1)
            perror("inotify_add_watch");

        printf("Watching %s using wd %d\n", argv[j], wd);
    }

    inotify_rm_watch(inotifyFd, wd);

    for (;;) {                                  /* Read events forever */
        numRead = read(inotifyFd, buf, BUF_LEN);
        if (numRead == 0)
            perror("read() from inotify fd returned 0!");

        if (numRead == -1)
            perror("read");

        printf("Read %ld bytes from inotify fd\n", (long) numRead);

        /* Process all of the events in buffer returned by read() */

        for (p = buf; p < buf + numRead; ) {
            event = (struct inotify_event *) p;
            displayInotifyEvent(event);

            p += sizeof(struct inotify_event) + event->len;
        }
    }

    exit(EXIT_SUCCESS);
}
@dmatveev
Copy link
Owner Author

dmatveev commented Mar 7, 2015

Could not reproduce on my NetBSD-CURRENT'13.

@wulf7
Copy link
Contributor

wulf7 commented Mar 7, 2015

I know of it and it stated at line 137 of README in wulf7/integrate-dmatveev branch:

**** Libinotify-kqueue behaves as IN_EXCL_UNLINK flag is always set

Most probably it started with commit 9d09b2c
Bad thing here that i dont know easy way to implement behavior of inotify watch created with IN_EXCL_UNLINK flag unset without introducing memory leaks

I can tell you whats going on here in details but not just now due to ENOTIME. Maybe tomorrow or in a few days

Do you now any practical use of running inotify with IN_EXCL_UNLINK flag unset?

P.S. And it not crashes for me. Just sends IN_IGNORE and stops watching as intended

@wulf7
Copy link
Contributor

wulf7 commented Mar 7, 2015

Hmm. Are you asked about crash or about inability of receiving events from deleted but still opened files?

@wulf7
Copy link
Contributor

wulf7 commented Mar 7, 2015

Ooops. Sorry. I misunderstood a code in test case. My comment is correct but irrelevant to issue

@dmatveev
Copy link
Owner Author

dmatveev commented Mar 7, 2015

Hi Vladimir, glad to hear from you.

Actually, there was an e-mail thread and you had been put into copy, though Mikhail (the reporter) said that messages are not delivered to you. Can you please recheck?

Mikhail reported that after commit 271ef97 (where some loops were modified as in worker_add_or_modify) he started to observe crashes in some apps which use libinotify.

This test should prove that, though I failed to reproduce anything, I am trying to get more details now.

@wulf7
Copy link
Contributor

wulf7 commented Mar 8, 2015

Got it! Try following patch:

diff --git a/worker-sets.c b/worker-sets.c
index 504b8cf..442adf5 100644
--- a/worker-sets.c
+++ b/worker-sets.c
@@ -83,7 +83,6 @@ worker_sets_extend (worker_sets *ws,
             return -1;
         }
         ws->watches = ptr;
-        ws->watches[0] = NULL;

         ws->allocated = to_allocate;
     }

@wulf7
Copy link
Contributor

wulf7 commented Mar 8, 2015

Actually, there was an e-mail thread and you had been put into copy, though Mikhail (the reporter) said that messages are not delivered to you. Can you please recheck?

Unfortunately, my personal mail server lost rackspace in datacentre about month ago so I cant respond on any mails till I find another place for it

@wulf7
Copy link
Contributor

wulf7 commented Mar 8, 2015

One should set a watch on directory with number of entries more than WS_RESERVED (10) to trigger this issue. That`s why it was not discovered with test suite

@dmatveev
Copy link
Owner Author

dmatveev commented Mar 9, 2015

Really, the issue was there. Thanks!

BTW, how do you debug libinotify? I do not remember if I had any issues four years ago, but in my current NetBSD installations I just can not hook into library's functions with gdb for step-by-step debugging (it can not find any debug symbols), though all flags required for that are present.

@wulf7
Copy link
Contributor

wulf7 commented Mar 10, 2015

how do you debug libinotify?

I replace -DNDEBUG with -DDEBUG in Makefile.am to enable assertions then set environment variables CFLAGS=-g -O0 CXXFLAGS=-g -O0 before configure stage to add debugging info and then run configure with --enable-perrors. Sometimes I run tests under valgrind control but not very often as it requires some level of source patching to workaround some valgrind porting deficiencies and FreeBSD lpthread bugs
And I'm using post-mortem analysis of core dumps and debugging printfs mostly rather then step-by-step tracing as code base and execution paths are not very complex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants