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

Renaming a file 12+ characters long freezes the app #52

Closed
SpartanJ opened this issue Nov 18, 2013 · 15 comments
Closed

Renaming a file 12+ characters long freezes the app #52

SpartanJ opened this issue Nov 18, 2013 · 15 comments
Labels
bug Something isn't working major

Comments

@SpartanJ
Copy link
Owner

Original report by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


If you rename a file that's 12 or more characters long (not including the extension), it causes the program to freeze.

For instance, renaming redrectangle.png to redrectangle2.png causes a freeze. Renaming it to a shorter length, such as redrect.png, also causes a freeze.

Adding/deleting/moving does not.

Windows 7 x64

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


This happens to you in the sample application that comes with the library?
I can't replicate it at all. Where the program is freezing? Please debug and pause the application when it freeze. It shouldn't be possible that efsw freeze your application since it runs in its own thread. May be you're locking the thread in the handleFileAction call? I need more information to resolve this issue.

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


This is in a GUI application, not a console one. More specifically, it's an OpenFL/Haxe game. I'm loading your library as an extension, and everything seems to be going well except for this.

Can't seem to replicate using the included sample.

I'm using FlashDevelop as my IDE, not entirely sure how to use their debugging tools. Thinking they might only work for Flash targets (and I'm targeting CPP) as setting a breakpoint does nothing.

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


Sorry, but it seems to be an invalid bug report. Since the problem is in the extension wrapper for Haxe.
I have never worked with Haxe, so, i know very little about it. But it seems that the problem relies in the wrapper that you did to work with efsw from Haxe. May be you can try to use the C wrapper provided by the library, since is more generic. It seems to me that the problem must come from the type conversion from std::string to the generic type for Haxe. But, as i said before, i know nothing about this.

Regards,

Martín

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


You may be right about the type conversion, but as far as I am aware, with the way I have it working currently, there is no type conversion.

All I'm doing now is exposing a method void Watch(); which is called from the Haxe application. I'm not passing any arguments or returning anything to Haxe itself, all the rest happens via CPP (essentially just the running the example on the overview page).

I'll try using the C wrapper to see if this fixes things, or else try to figure out what the heck is happening. Even if I comment out the switch statement in handleFileAction, it still freezes.

I should note that I've successfully created my own custom extension for FindFirstChangeNotification / FindNextChangeNotification as well as QFileSystemWatcher. Both of which were working and I never saw any freezing, they just didn't quite function as well as I needed them too. (Needed to really switch to ReadDirectoryChangesW and was hard to find any good examples, plus I'd still have to write all the MacOS and Linux code myself, and QFileSystemWatcher isn't recursive so you have to manually add a path for every directory / file you wish to watch, which isn't ideal, not to mention the addition of ~35MB worth of QT libraries needed just to run the thing!)

Thanks for the fast responses! Appreciate it.

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


Don't you think it's peculiar that it's only freezing for me when I rename the file? Any other action works just fine.

It's the exact same handleFileAction method that is being called on my end, which is making me think it's something in the library itself.

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


Haha i understand you, this library exists exactly for the reasons you named! I never found a solution that satisfied me 100 %.

It's really weird, and i would love to help you, but i don't know exactly how!
May be you can send me an complete example showing me the freeze. And i'll try to debug it. Are you static linking the library or using the dll?

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


It's really peculiar, but i can't replicated! And this is something that only happened to you ( there are users using the library ), so, i don't know what to think. I don't want to blame you at all, this could be the library, but i need some proof.

In the other hand, i don't understand how is your application freezing ( can you explain me better what's happening? ). May be there's some problem with threads and Haxe?

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


And I'm very glad it does! I first found SimpleFileWatcher, but it hadn't been updated since 2010, so I wasn't too keen on using it. With a bit more searching, I stumbled on this and recognized the example code right away. I knew this had to be based on SFW, found the credit at the bottom :)

I realize I'm not exactly making it easy for you to help :P Since it's a Haxe app, it won't be the easiest for you to test on your own (took a while to figure out extensions -- not very well documented officially, found a few good blog posts about it though). Here are a few key points that may help, however:

  • I'm using the dll
  • I'm using efsw.hpp
  • The code I'm running is essentially the example on the overview
  • Every other action works, except for renaming
  • The app is running from C:\Game\Export\windows\neko\Game.exe
  • The folder I'm watching is C:\Game\Assets\textures
  • I'm using building using a "neko" target instead of a pure cpp target (not entirely sure of the difference, all I know is it produces a smaller exe, so I went with that... I'll try targeting cpp to see if that makes a difference later tonight)

Here's the relevant code. If you spot anything out of the ordinary, let me know!

#!c++

#ifndef ASSETWATCHER_H
#define ASSETWATCHER_H

#include <iostream>
#include "efsw.hpp"

using namespace efsw;

namespace assetwatcher {
	
	class Notifier : public FileWatchListener {
		void handleFileAction(WatchID handle, const std::string& dir, const std::string& filename, Action action, std::string lastFilename = "");
	};
	
	FileWatcher *fileWatcher;
	Notifier    *notifier;
	
	void Watch();
	
}

#endif

#!c++

#include "Utils.h"

namespace assetwatcher {
	
	void Notifier::handleFileAction(WatchID handle, const std::string& dir, const std::string& filename, Action action, std::string lastFilename) {
		switch (action) {
			case Actions::Add:
				std::cout << "File added: " << filename << std::endl;
				break;
				
			case Actions::Delete:
				std::cout << "File deleted: " << filename << std::endl;
				break;
				
			case Actions::Modified:
				std::cout << "File modified: " << filename << std::endl;
				break;
				
			case Actions::Moved:
				std::cout << "File moved: " << filename << std::endl;
				break;
		}
	}
	
	void Watch() {
		notifier = new Notifier();
		
		fileWatcher = new FileWatcher();
		fileWatcher->addWatch("C:/Game/Assets/textures", notifier, true);
		fileWatcher->watch();
		
		std::cout << "Watching: C:/Game/Assets/textures" << std::endl;
	}
	
}

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


Everything looks fine! This must be something the threading and how the binding works... or something like that... well i really have no idea what to think!

I'm willing to help you if you send me a good and simple example with this failing, and at least a simple explanation on how to compile it and make it work ( and then fail! ).

The other thing that you can try is to compile efsw as an static library.

Regards,
Martín

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


Okay, so I've tried tweaking the source code a bit, and I've managed to figure out what's causing the freezing... just not sure how to fix it or why it's even happening at all.

Sending watch->OldFileName as an argument in this line is the cause of the problem.

  • If I remove it, no more freezing.
  • If I change it to "hello.png", no more freezing.
  • However, if I change it to "thisstringismorethan12charslong.png", it freezes once again.

This must be Haxe related then, right? Is it possible to switch OldFileName from std::string to const std::string&? Haxe seems to have no problems with that. Otherwise, I could try using the C wrapper, though it looks a lot more complicated. Is there any example available?

I could also try posting this on the Haxe forum and see if they can figure out a solution.

If all else fails, I may be able to simply keep the temporary fix I have now, and workaround not having access to the old file name.

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


Oh! I thought about that, but as you said that from Haxe you were only using the "Watch()" call, i discarded the idea. This is a very common problem with language bindings. Sadly i can't change std::string to const std::string&, since that would break any application that is already using the library ( because they would need to rename the declaration of the pure virtual function handleFileAction ). But the fix should be really easy, just do something like:

#!c++

    class Notifier : public FileWatchListener {
        void haxeHandleFileAction(WatchID handle, const std::string& dir, const std::string& filename, Action action, const std::string& lastFilename)
        {
                // you bind this, not the other one
        }

        void handleFileAction(WatchID handle, const std::string& dir, const std::string& filename, Action action, std::string lastFilename = "")
        {
                haxeHandleFileAction( handle, dir, filename, action, lastFilename );
        }

    };

And use you own function from Haxe instead the handleFileAction. But i'm not sure how your binding works. May be i'm confused.

The C wrapper is simple as the C++ version:

#!c
// Your callback to get the file system events
void file_event_callback(efsw_watcher watcher,
    efsw_watchid watchid, const char* dir, const char* filename,
    enum efsw_action action, const char* old_filename, void* param)
{
    
}

// Create a File Watcher
efsw_watcher watcher = efsw_create(0); // 0 to use the OS native watcher

// Watch a directory
// 1 = is resursive. The last parameter is a custom user param, to pass information to the watcher callback
efsw_addwatch( watcher, "YourDirToWatch", file_event_callback, 1, NULL );

// Start the watcher
efsw_watch( watcher );

...

// then at the end of the application you can release the watcher:
efsw_release( watcher );

As you can see, it's actually the same.

Regards,
Martín

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


Sorry, guess that line was a bit misleading. I am creating a "Neko DLL" (.ndll) file that has the code I posted in it and is built using hxcpp (Haxe CPP, I reckon'). I'm exposing a single method (void Watch) through that .ndll, which my Haxe application calls. That then loads the code from efsw using the .dll I generated from your library and calls as needed.

So it's:

Haxe (the app) => Neko DLL (the extension) => efsw DLL


Thanks for all the help! I'll try this and see if it works when I get home.

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


Freezes just the same using the haxeHandleFileAction method; however, the C wrapper seems to work just fine! Thanks for that example code, it helped a lot.

@SpartanJ
Copy link
Owner Author

Original comment by Martín Lucas Golini (Bitbucket: SpartanJ, GitHub: SpartanJ).


Excellent! I'm glad that it worked.

Now i'm in doubt if it would be better to change that std::string to const std::string&. I'm gonna think about it, since is a very trivial change to the users using the library too.

I'm gonna ask you same favor if you have time.
Can you try to ask in the neko forums what was the problem with the default argument passed as value? Usually scripting bindings have some limitations, but this one is weird.

Regards,
Martín

@SpartanJ
Copy link
Owner Author

Original comment by Kevin Jurkowski (Bitbucket: Driklyn, GitHub: Driklyn).


Sure thing, I just posted an issue about it. I'm pretty curious about the reason behind it as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working major
Projects
None yet
Development

No branches or pull requests

1 participant