Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 5

Qt-interest Archive, December 2006
QFileSystemWatcher and QtService - does not work?


Message 1 in thread

Hi,

I'm trying to observe the changes of a directory from within a QtService
(Qt solution), but I never receive a signal 'directoryChanged' nor
'fileChanged'.

I've added two dummy objects, a directory c:\temp\in and
c:\temp\in\test.txt. I add files to c:\temp\in and I change the text
file, but nothing, nada, no signals! Off course the file and directory
exist at the time of calling addPath().

I've set a break point in the corresponding slot and even write a log
entry, but obviously the slot gets never called. According to the
QFileSystemWatcher::files() and ::directories() the files are indeed
being watched.

First I had my service derived from a QCoreApplication, I've also tried
subclassing from QApplication (in case some event queue or other
initialisation was missing in QCoreApplication, but I guess
QFileSystemWatcher should also work in a "QCoreApplication" only), no
difference.

Before digging any deeper: Could it be that the QFileSystemWatcher does
not work from within services? Am I missing a crucial thing here?

Basically I have this:

class OOoService : public QObject, public QtService<QApplication> {...}

void OOoService::start() {
  m_d->m_fileSystemWatcher = new QFileSystemWatcher (this);
  /*! \todo Hardcoded for now; read path from *.ini config file! */
  m_d->m_fileSystemWatcher->addPath ("c:\\Temp\\in");
  m_d->m_fileSystemWatcher->addPath ("c:\\Temp\\in\\test.txt");
  this->connect (m_d->m_fileSystemWatcher, SIGNAL (directoryChanged
(const QString &)),
                 this, SLOT (handleDirectoryChanged (const QString &)));
  this->connect (m_d->m_fileSystemWatcher, SIGNAL (fileChanged (const
QString &)),
                 this, SLOT (handleFileChanged (const QString &)));
  ...
}

void OOoService::stop() {
  delete m_d->m_fileSystemWatcher;
}

// slots
void OOoService::handleDirectoryChanged (const QString &path)
{
  // never called
  this->logMessage (QString ("Dir. '%1' has changed.").arg (path),
QtServiceBase::Information);
}

void OOoService::handleFileChanged (const QString &path)
{
  // never called
  this->logMessage (QString ("File '%1' has changed.").arg (path),
QtServiceBase::Information);
}



As seen on Qt 4.2.0 (haven't tried 4.2.2 yet) on Windows XP SP2 Professional


Cheers and Merry Xmas! Oliver

--
 [ signature omitted ] 

Message 2 in thread

Till Oliver Knoll schrieb:
> Hi,
> 
> I'm trying to observe the changes of a directory from within a QtService
> (Qt solution), but I never receive a signal 'directoryChanged' nor
> 'fileChanged'.

Hmmm... same thing with the current Qt 4.2.2, QFileSystemWatcher does
not emit any signals when I change the file (by editing and saving it
with some text editor) or the directory (by creating new files with the
File Explorer in that directory).

Needless to say that the QFileSystemWatcher, used in the same way, works
in another test (GUI) application as expected.

Does that have to do with an event queue not being there in a QtService
or the like or that services are somehow restricted to receive these
kind of file system events? Anyone got experience with this?

I forgot: QtService is version 2.2 (with some patch applied, so it
terminates/pauses properly)


Thanks and Happy New Year! Oliver

--
 [ signature omitted ] 

Message 3 in thread

Till Oliver Knoll schrieb:
> > Till Oliver Knoll schrieb:
>> >> Hi,
>> >> ...
> > Does that have to do with an event queue not being there in a QtService
> > or the like or that services are somehow restricted to receive these
> > kind of file system events? Anyone got experience with this?

Just for completeness sake: By now I have also tried running the service
under my own user account (previously it was the "system" account with
the checkbox "Allow data exchange between service and desktop" checked,
see "Properties" from the service in the Windows service manager
console) - no difference.

Cheers, Oliver





--
 [ signature omitted ] 

Message 4 in thread

On Friday 22 December 2006 15:22, Till Oliver Knoll wrote:
> Does that have to do with an event queue not being there in a QtService
> or the like or that services are somehow restricted to receive these
> kind of file system events? Anyone got experience with this?

I took a very short look at qfilesystemwatcher.cpp and think that the 
extraordinary answer to your question is: yes, it does have to do with the 
event loop! The default implementation of the watcher seems to use  a 
QTimer to check whether the file has been changed in intervals.

Rewrite your service to have an event loop (QCoreApplication::exec plus some 
non-blocking in the code should do the trick). Just out of complete 
dumbness on my part: why use Qt in the first place if you don't want to use 
the event loop?


	Konrad

Attachment:

Attachment: pgpiQPERvv6gd.pgp
Description: PGP signature


Message 5 in thread

Konrad Rosenbaum schrieb:
> On Friday 22 December 2006 15:22, Till Oliver Knoll wrote:
>> Does that have to do with an event queue not being there in a QtService
>> or the like or that services are somehow restricted to receive these
>> kind of file system events? Anyone got experience with this?
> 
> I took a very short look at qfilesystemwatcher.cpp and think that the 
> extraordinary answer to your question is: yes, it does have to do with the 
> event loop! The default implementation of the watcher seems to use  a 
> QTimer to check whether the file has been changed in intervals.

Hmmm, in the meantime I did some search in the MSDN and came up with the
Win32 API function FindFirstChangeNotification. I didn't have a look yet
into the Qt sources, but I'm surprised that you mention a QTimer being
used instead - is this really the implementation being used on Win32?

Well anyway, the FindFirstChangeNotification is a blocking function and
is to be used within a thread. I assume that this thread would fire a Qt
signal and since this signal would be an asynchronous signal a proper
event queue would be neede in the "application", or in my case in the Qt
"service".

(A QTimer also needs an event queue running, so the following arguments
apply there, too)

Since I'm also not familiar with the QtService implementation yet I'm
not sure whether services have an event queue, but given the fact that I
have to call

  return service.exec();

in my main() function it thought there _was_ some kind of event queue in
a QtService (I think service.exec() really doens't return until the
service is terminated, since it still has to react on "service messages"
such as "pause", "resume" etc.).

> 
> Rewrite your service to have an event loop (QCoreApplication::exec plus some 
> non-blocking in the code should do the trick). Just out of complete 
> dumbness on my part: why use Qt in the first place if you don't want to use 
> the event loop?

It's not like I don't want to use an _event loop_ (I'm perfectly fine
with an event loop :), it's more like I don't feel writing my own
service class when there's one ready written by Trolltech (see "Qt
solutions" on their web page) and hence I want to use QtService ;)

So the question is hence: does the QtService class have a proper event
loop which can either react to asynchronous signals or QTimer events
(depending on what implementation is really used in
qfilesystemwatcher.cpp) or not? Seems like I really have to dig into the
QtService.cpp implementation ;)

Cheers, Oliver

--
 [ signature omitted ] 

Message 6 in thread

Till Oliver Knoll schrieb:
> Konrad Rosenbaum schrieb:
>> On Friday 22 December 2006 15:22, Till Oliver Knoll wrote:
>>> Does that have to do with an event queue not being there in a QtService
>>> ...
>> I took a very short look at qfilesystemwatcher.cpp and think that the 
>> extraordinary answer to your question is: yes, it does have to do with the 
>> event loop! The default implementation of the watcher seems to use  a 
>> ...
> in my main() function it thought there _was_ some kind of event queue in
> a QtService (I think service.exec() really doens't return until the
> service is terminated, since it still has to react on "service messages"
> such as "pause", "resume" etc.).

Well that's actually wrong, exec() _does_ return immediatelly. From the
QtService docs:

  "In the end, exec() returns while the service continues in its own
   process waiting for commands from the service controller."

This sounds more like services don't have a proper event queue but wait
for events as propagated by the "service controller" (implemented by the
operating system I guess).

--
 [ signature omitted ] 

Message 7 in thread

Till Oliver Knoll schrieb:
> Till Oliver Knoll schrieb:
>> ...
> This sounds more like services don't have a proper event queue but wait
> for events as propagated by the "service controller" (implemented by the
> operating system I guess).

Thinking about this some 5 minutes more the "engineer solution" would be
simply launching a proper QCoreApplication *.exe from within the
QtService rather than breaking my head whether QtService has or has not
an event queue and if not "how could I add one":

  OOoService::start() {
    QProcess process;
    ...
    process.start ("appWithAnEventQueueAndWhichUsesQFileSystemWatcher");
    ...
  }

Should work... ;)

Cheers, Oliver

--
 [ signature omitted ] 

Message 8 in thread

Till Oliver Knoll schrieb:
> Till Oliver Knoll schrieb:
>> Till Oliver Knoll schrieb:
>>> ...
>> This sounds more like services don't have a proper event queue but wait
>> for events as propagated by the "service controller" (implemented by the
>> operating system I guess).
> 
> Thinking about this some 5 minutes more the "engineer solution" would be
> simply launching a proper QCoreApplication *.exe from within the

Going over this another 10 minutes made me remember the HttpService
example (which ships together with the QtService solution). A QTcpServer
is used there which for sure also needs an event queue running!

So I made my project analogous to this example, creating a separate
class "BigBrother" derived from QObject (in analogy to HttpDaemon in the
HttpService example):

// WORKS now!
class BigBrother : public QObject
{
    Q_OBJECT

public:
    BigBrother (QObject *parent);
    ~BigBrother();

    void setDirectoryPath (const QString &newDirectoryPath);
    QString getDirectoryPath() const;

private:
    BigBrotherData *m_d; // contains the QFileSystemWatcher

private slots:
    // connected with the QFileSystemWatcher
    void handleDirectoryChanged (const QString &path);
};

Now within my "OOoService" (derived again from
QtService<QCoreApplication>) I allocate this BigBrother on the heap, as
is done in the HttpService example (don't now if that makes a
difference, but I didn't try allocating it on the stack), giving the
QCoreApplication as parent:

void OOoService::start()
{
    QCoreApplication *app = application();

    m_d->m_bigBrother = new BigBrother (app);
    m_d->m_bigBrother->setDirectoryPath ("c:\\Temp\\in");
}

void OOoService::stop()
{
    if (m_d->m_bigBrother != 0)
    {
        delete m_d->m_bigBrother;
        m_d->m_bigBrother = 0;
    }
}

Now my slot 'handleDirectoryChanged' is indeed called when I modify the
test directory "c:\Temp\in" :)

To be honest I have not an exact clue why it works this way and not the
other way I had previously:

// does NOT work
class OOoService : public QObject, QtService<QCoreApplication>
{
...
private slots:
    // is never called
    void handleDirectoryChanged (const QString &path);
};

But I believe it has to do with the fact that I allocated the
QFileSystemWatcher in the c'tor of OOoService, at a point where maybe no
QCoreApplication was created or so, and maybe QFileSystemWatcher depends
on a QCoreApplication being already initialised etc. can't remember
exactly my previous implementation.

Anyway it works now and I am happy :)

Happy New Year! Oliver

--
 [ signature omitted ] 

Message 9 in thread

On Wednesday 27 December 2006 11:16, Till Oliver Knoll wrote:
> Hmmm, in the meantime I did some search in the MSDN and came up with the
> Win32 API function FindFirstChangeNotification. I didn't have a look yet
> into the Qt sources, but I'm surprised that you mention a QTimer being
> used instead - is this really the implementation being used on Win32?

I admit I only looked into the sources for X11, but what I found seemed to 
be the default implementation for all platforms. I'm not sure whether there 
is something special in the win32 part of it though

Sorry, I don't know anything about QtService, since I'm neither a Qt 
solutions customer, nor do I intend to write a win32 service anytime soon. 
Good hunting!... ;-)


	Konrad

Attachment:

Attachment: pgpjsbH98haLB.pgp
Description: PGP signature


Message 10 in thread

Hi,

> I'm trying to observe the changes of a directory from within a QtService
> (Qt solution), but I never receive a signal 'directoryChanged' nor
> 'fileChanged'.

Does it work with "regular" Qt Applications?

> First I had my service derived from a QCoreApplication, I've also tried
> subclassing from QApplication (in case some event queue or other
> initialisation was missing in QCoreApplication, but I guess
> QFileSystemWatcher should also work in a "QCoreApplication" only), no
> difference.

Yes, it should work with QCoreApplication:
	The application type can be QCoreApplication for services
	without GUI, QApplication for services with GUI or you can
	use your own custom application type.

--
 [ signature omitted ] 

Message 11 in thread

Dimitri schrieb:
> Hi,
> 
>> I'm trying to observe the changes of a directory from within a QtService
>> (Qt solution), but I never receive a signal 'directoryChanged' nor
>> 'fileChanged'.
> 
> Does it work with "regular" Qt Applications?

Yes it does, as written in a later post of mine.

> 
>> First I had my service derived from a QCoreApplication, I've also tried
>> subclassing from QApplication (in case some event queue or other
>> initialisation was missing in QCoreApplication, but I guess
>> QFileSystemWatcher should also work in a "QCoreApplication" only), no
>> difference.
> 
> Yes, it should work with QCoreApplication:
>     The application type can be QCoreApplication for services
>     without GUI, QApplication for services with GUI or you can
>     use your own custom application type.

The question is hence: does it also work with

  class OOoService : public QObject, public QtService<QApplication>

or

  class OOoService : public QObject, public QtService<QCoreApplication>

?

Given the fact that it _does_ work with stand-alone (Core-)applications
and does _not_ work with QtService makes me think that services simply
don't have an event queue which could handle QTimer events or
asynchronous signals (see other posting). Is that correct?

Cheers, Oliver

--
 [ signature omitted ]