View Full Version : plugins & threads...
21st August 2004, 18:51
okay, this question is complicated by the fact that i'm doing a winamp plugin for the first time, and by the fact that it's being done in C#, so bear with me...
here's what i'm doing:
- on winamp launch, i launch my plugin (in init, i call Show() on my dialog).
- in init, i'm loading up a large-ish database. i don't want to delay winamp (i want the user to be able to start using winamp right away, while my plugin is still loading), so i've got the load operation happening on a separate thread.
now, is there a reason why this would cause a plugin crash when i click configure? or why winamp decides not to call quit() when it closes?
i've narrowed it down to the thread thing - if i launch the thread, if i load the database, then the plugin crashes on configure and quit() never gets called. if i don't launch the thread, everything works as it should.
what's up? any ideas?
22nd August 2004, 03:30
Cant you just disable SEH and run it through a debugger?
22nd August 2004, 07:12
it's not crashing in any of my code. it's crashing because winamp is trying to access bad memory. winamp.exe is on top of the stack.
none of my code is even touched - everything runs fine until i close winamp, and then winamp decides to go after some memory that it shouldn't, and crashes.. i put a breakpoint in every single method of every class in my code, and nothing gets called after i click the close button. winamp just crashes.
it's strange --- it's definitely caused by the thread (if i don't put the load call on a separate thread, everything's okay), and it's definitely caused by the fact that i'm loading data from a file (if i don't, and just let the thread spin its wheels for 30 seconds, everything is okay), but i can't see any reason why any of that should cause winamp to crash.
it's also doesn't matter *what* data i load, or how i load it. i thought for awhile it might be a bug with my database load mechanism, so, to verify if that was the problem or not, i removed the database load call entirely, and replaced it with a simple bit of code to quickly read a small textfile. it crashes, so it's not my load() that's responsible.. it crashes if i access any file from a thread.
is there a reason? why can't i read data from a separate thread?
22nd August 2004, 07:26
Hmm, I dont have much experience with C#, so Im not sure how well winamp behaves with that.
Does it crash when reading the file, or when calling configure()? Have you tried not doing anything in the thread at all? esp involving IO. I'd imagine its somehing to do with the thread cleanup rather than the actual file access.
Does the thread exit befoire configure is called? Are you passing a valid pointer to a 'config' function? Perhaps when you start creating threads in C# those pointers become invalid? (ie, it may not be your code, but perhaps it _was_ your code that existed at that location but now the memory address is invalid when winamp tries to call it) I do not know how C#/.net handles pointers and calls from native applications so I cant help you much there.
22nd August 2004, 07:44
yeah, it's possible that it is the C# thing. i'm new to com/.net interop... but, it's just so weird, because the crash really doesn't seem to have anything to do with that. it all works 100% *perfectly* unless i read a file from within a thread. then it crashes. strange, strange.
to answer your questions:
--is there a crash when reading the file?
--crash when calling configure()?
no, not really. it'll crash if i click the configure button, but configure() (my code) never gets called. if i *don't* click configure, the crash waits until i close winamp.
-- is it maybe thread cleanup?
i'm not sure about that. i'm using pretty standard C# threads, and the data that i read from the text file was read and discarded immediately - nothing else touched it. i forced garbage collection after the thread was finished, as well.
-- does the thread exit before configure is called?
yeah, long before.
-- are you passing a valid pointer to the config function?
yeah, because if i don't load the data in a separate thread, there is no crash. configure() and quit() get called correctly.
-- do the pointers become invalid when i create threads?
no, because if i don't access a file inside of that thread, everything works fine. that is, if i just create a thread and let it spin for awhile, and then close winamp, i get no crash. it's only when there's file access within that thread that i get the crash. but yeah, it is suspicious that the crash is happening at right about the time that winamp should be calling configure() or quit(). and that it's a bad memory access...
i'm going to regret having used C#, i can tell. it's probably doing something behind my back that i didn't ask it to do...
22nd August 2004, 09:15
I would expect its a pointer issue with init and config. Perhaps try passing invalid pointers for the 'getplugin' function and see if it crashes at the same location. You should be able to determine if that is indeed the problem then.
Also, try printing out the address of config() at init or getplugin..() and see if it is the location that winamp is trying to access when it crashes.
If it does turn out to be the issue, Im sorry but I dont know enough about interop to give you any advice :P (other than dont use c# :)
22nd August 2004, 19:37
aha, fixed it.
turns out, when you're using a combination of managed code (garbage collected code - my plugin) and unmanaged code (winamp), the garbage collecter has no real way to know if the unmanaged code is hanging on to some bit of the managed code. in my case, it was (it had function pointers to the init, quit, config methods on a small proxy object that I created to sit in between winamp and my C# code), but the garbage collecter didn't know that and was destroying my proxy object.
fixing it was a pain, because the garbage collecter isn't very smart. there's no way to say "look, just don't ever collect this object until i tell you otherwise." i had to add a bit of a hack to the destructor of my proxy object, which more or less 'aborts' destruction... i don't totally trust this solution, but it seems to work for now.
why it only happened when data was being loaded in a separate thread, i have no idea -- maybe that combination triggers the garbage collecter or something?
by the way - thanks for the help, shaneh. it was your question about the pointers becoming invalid that prompted me to look in that direction..
23rd August 2004, 02:24
Cool, I was going to mention the stuff about the garbage collection actually - you metnioned you forced it after the IO stuff... pointers to code and a runtime which shuffles memory about dont mix too well ;)
But just removing the forced garbage collection wouldnt fix it as the clr does it automatically from time to time. (doing some IO in another thread which then gets destroyed would be a perfect example)
Take a look at:
Especially point 4. You should be using the 'DllImportAttribute' attribute on the config and init functions I suspect. You might like to also check out __nogc, but I think DllImportAttribute should do it.
But just 'aborting' destruction isnt too great, as the runtime could potentially still move your object about, if it finds a more suitable memory slot for it for eg. This is unlikely to happen, but you probably shouldnt depend on that.
vBulletin® v3.8.6, Copyright ©2000-2013, Jelsoft Enterprises Ltd.