From owner-freebsd-questions@FreeBSD.ORG Tue Apr 10 19:52:15 2012 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 33B041065677 for ; Tue, 10 Apr 2012 19:52:15 +0000 (UTC) (envelope-from ben@benshort.co.uk) Received: from mail-lpp01m010-f54.google.com (mail-lpp01m010-f54.google.com [209.85.215.54]) by mx1.freebsd.org (Postfix) with ESMTP id 919678FC18 for ; Tue, 10 Apr 2012 19:52:14 +0000 (UTC) Received: by lagv3 with SMTP id v3so186830lag.13 for ; Tue, 10 Apr 2012 12:52:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type:x-gm-message-state; bh=GHxlOtiFdZcKylko1q3eUtKDKB+lCVUblqfNxxS7ydw=; b=iLealRdRYQ1VLxrunJ3F0f33hnOrBOlU9fi/M6myZ0qrxY/Yl8kwXWXLj8HrMfjHg2 ELuo89KyZVW+/VHstkN5X4ReYeoRG2fUk/RlOrQrby786J2ZANhube3K12OJo5yp+VX3 D0R9F9wBq5tC8ZuvxjimexNdG8PgQI0QJGL/YoQftND3pbrvz305eleePZ5Qo6yZhGAt aU8axayQF6O6Ufinnmj+CfdY5oBBFTJf0r0Bv7ROjMEHmuS2mG+thmEgQSoY4i5hojxS ZSwxBk1QMhT4vEjLP7duSFlC2j4EcXY9bm6hTs89uc+/1myP7VUE6eGA9MTFRf7a2lVf 4Gog== MIME-Version: 1.0 Received: by 10.112.100.170 with SMTP id ez10mr1823014lbb.15.1334087533504; Tue, 10 Apr 2012 12:52:13 -0700 (PDT) Received: by 10.112.110.131 with HTTP; Tue, 10 Apr 2012 12:52:13 -0700 (PDT) In-Reply-To: References: Date: Tue, 10 Apr 2012 20:52:13 +0100 Message-ID: From: Ben Short To: freebsd-questions@freebsd.org X-Gm-Message-State: ALoCoQnk3vZBtNPBBLmHnHdjfTqJUW7+1SzOcAu/OS29bjR4+o36xTm1PiZzz8QRkCLDoeceGSUy Content-Type: text/plain; charset=ISO-8859-1 X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: Re: Using kqueue with 2 threads X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Apr 2012 19:52:15 -0000 I have put together the following example and can still see the problem. Once the file is written to extended is printed every second. If I remove the sleep then it prints a whole lot more. So it seems that the call to kevent in the worker_thread method blocks until the file is written to then it returns the same event straight away on every call. Is this expected? Am I meant to clear the event some how? #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; struct wrapper { int kq; }; static void* worker_thread(void* obj) { int kq = ((wrapper*)obj)->kq; std::cerr << "Started worker" << std::endl; struct kevent ke; int i; while ( 1 ) { memset(&ke, 0x00, sizeof(ke)); i = kevent(kq, NULL, 0, &ke, 1, NULL); if ( i == -1 ) { std::cerr << "kqueue produced error: " << strerror(i) << std::endl; continue; // todo is this the best thing todo? } else if ( i == 0 ) { std::cerr << "kqueue time limit expired" << std::endl; continue; } if ( ke.filter == EVFILT_VNODE ) { if ( ke.fflags & NOTE_DELETE ) { std::cerr << "delete" << std::endl; break; } else if ( ke.fflags & NOTE_RENAME ) { std::cerr << "rename" << std::endl; } else if ( ke.fflags & NOTE_EXTEND ) { std::cerr << "extended" << std::endl; } else { std::cerr << "some other fflags" << std::endl; } } else { std::cerr << "some other filter" << std::endl; } sleep(1); } std::cerr << "Shutting down worker" << std::endl; return 0; } void writeToFile(std::string fileName, std::string key, std::string value) { std::fstream registryEntry; registryEntry.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { registryEntry.open(fileName.c_str(), std::ios::out | std::ios::binary); size_t keyLength = key.length(); registryEntry.write((char*)&keyLength, sizeof(size_t)); registryEntry.write(key.c_str(), key.length()); size_t valueLength = value.length(); registryEntry.write((char*)&valueLength, sizeof(size_t)); registryEntry.write(value.c_str(), value.length()); std::cout << "Set entry with key: " << key << std::endl; } catch (std::ifstream::failure e) { // todo throw exception std::cerr << "Failed to set registry entry. Error: " << e.what() << std::endl; } registryEntry.close(); } void test2() { int kq = kqueue(); if ( kq == -1 ) { std::cerr << "Failed to create kqueue. Error: " << strerror(errno) << std::endl; return; } pthread_t worker; wrapper wrap; wrap.kq = kq; if ( pthread_create(&worker, 0, worker_thread, &wrap) != 0 ) { std::cerr << "Failed to create listener thread. Error: " << strerror(errno) << std::endl; } int fd = open("/tmp/tt", O_RDONLY); if ( fd == -1 ) { std::cerr << "Failed to open file: " << "/tmp/tt" << " Error: " << strerror(errno) << std::endl; // todo throw exception } struct kevent ke; EV_SET(&ke, fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME | NOTE_EXTEND, 0, NULL); if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) { std::cerr << "kevent produced error: " << strerror(errno) << std::endl; } sleep(1); writeToFile("/tmp/tt", "key1", "value1"); sleep(5); } /* * */ int main(int argc, char** argv) { test2(); return 0; } On 10 April 2012 15:25, Ben Short wrote: > Hi, > > I'm trying to use a kqueue to listen for VNODE events on a worker thread. > I want new events to be registered with the kqueue by a separate thread. > > I have been referring to this example [URL=" > http://doc.geoffgarside.co.uk/kqueue/file.html"] > http://doc.geoffgarside.co.uk/kqueue/file.html[/URL] > > Here are the relevant parts of code as it is at the moment. > > In my worker thread: > > [CODE]std::cerr << "Started worker" << std::endl; > > struct kevent ke; > int i; > > while ( !mStopRequested ) { > > memset(&ke, 0x00, sizeof(kevent)); > > i = kevent(kq, NULL, 0, &ke, 1, NULL); > if ( i == -1 ) { > std::cerr << "kqueue produced error: " << strerror(i) << > std::endl; > continue; // todo is this the best thing todo? > } > > std::cerr << "Beep: " << i << std::endl; > > } > > std::cerr << "Shutting down worker" << std::endl;[/CODE] > > Other thread > > [CODE]int fd = open(fileName.c_str(), O_RDONLY); > if ( fd == -1 ) { > std::cerr << "Failed to open file: " << fileName << " Error: " << > strerror(errno) << std::endl; > // todo throw exception > } > > struct kevent ke; > > EV_SET(&ke, fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME | > NOTE_EXTEND, 0, NULL); > > if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) { > std::cerr << "kevent produced error: " << strerror(errno) << > std::endl; > }[/CODE] > > > When I run my code the kevent call in the worker code doesn't block at > all. Any ideas what I'm missing? or if what I want to do is even possible? > > Ben >