Hot Door CORE Forum
callbacks that stop calling back - Printable Version

+- Hot Door CORE Forum (http://hotdoorcore.com/forum)
+-- Forum: All forums (http://hotdoorcore.com/forum/forumdisplay.php?fid=1)
+--- Forum: General discussion (http://hotdoorcore.com/forum/forumdisplay.php?fid=3)
+--- Thread: callbacks that stop calling back (/showthread.php?tid=243)



callbacks that stop calling back - Rick Johnson - 09-04-2020

I've got a situation that I understand nobody can possibly debug over a forum, but I hope someone has had some experience that can provide clues as to things to look for.

I have a plugin that creates artwork, either from a modal dialog called from a menu or with a tool that calls the modal dialog when clicked. Apparently, the dialog blocked something that did not want to be blocked. From the menu, within the first few uses the dialog no longer calls the callbacks for the OK or Cancel buttons. This happens regardless of whether the dialog is created with ButtonOptions or if the OK and Cancel buttons are created individually.

When called from the tool, the MouseUp callback is soon not called, although MouseDown and Drag callbacks continue to work.

Dismissing the dialog before beginning to draw didn't help. Push and Pop context didn't help. The draw functions are really pretty ordinary, creating path art or modifying existing paths, and doing a few string utility functions to scan and format measurements using the current ruler units.

My solution/workaround was to replace the modal dialog with a panel and from the menu just used fixed default values, but I'd like to get this to work sometime. Could it be calls to the SDK for AIUndo, AITransformAgain, AIUnicodeString, or AIActionManager, which are acquired at startup and released at shutdown?

Any theories or suggestions would be very much appreciated.


RE: callbacks that stop calling back - garrett - 09-28-2020

I have seen this kind of behavior before when a C++ exception is thrown during runtime but never caught; the dynamic library (in this case your plugin) seems to stop functioning but the host app (Illustrator) continues to work. Try checking any suspect code for uncaught exceptions and/or enable a breakpoint in your debugger to break on any uncaught exceptions.


RE: callbacks that stop calling back - Rick Johnson - 12-06-2020

Thanks, Garrett,

I may be in over my head, but I'll press on. Stopping on every exception makes a LOT of stops, but none I've seen so far with my plugin in the event chain, so I'm working on narrowing the scope down.

My main .cpp file has over 1,100 lines of code (including comments), so it may help to break it up into several separate classes. I have a couple for registration and preferences that require my main file to explicitly call startup, postStartup, etc. for each, but I imagine that's unavoidable, and need to do that for all.

Does this from the Xcode console offer any clues?

#
# Fatal error in v8::HandleScope::CreateHandle()
# Cannot create a handle without a HandleScope
#

It may be possible I'm doing something where I should use pushContext or popContext, but don't understand what that does or know where/how to learn about it. To be honest, my plugins are not that in-depth, pretty much like larger versions of the CORE sample projects.

In the meantime, I'm adding try/catch in hopes of finding something. If I discover something potentially useful to others, I'll report back.


RE: callbacks that stop calling back - garrett - 01-20-2021

Sorry, I somehow missed this response of yours from last month too. V8 is a JavaScript engine, so if that's the kind of error/exception you're looking at, then it's likely not your issue but something Illustrator is doing (or potentially someone else's plugin).

Pushing and popping context is required whenever your plugin is messaged through any other means than via Illustrator directly; which is to say, if your PluginMain() function (which hdi_core abstracts away so you don't have to deal with it) is NOT called, then you have to push context if you want to interact with Illustrator and pop context when you're done interacting with Illustrator. An example of this is when the OS itself messages your plugin, perhaps in response to e.g. some event in a custom widget you have created completely from scratch, or in response to a timer you registered directly with the OS, or response to your interacting with a third-party library that later calls your code of its own accord.


RE: callbacks that stop calling back - Rick Johnson - 01-28-2021

Thanks, Garrett, that's very helpful.

Regarding the original problem above, I think I found the offending code. I felt that Adobe's sAIUser->IUStringToAIReal didn't interpret user units as well as I'd wanted, so I wrote my own "scan" and "format" functions and added them to strFormatting.cpp from the sample code. It reads a wide variety of units expressed in different ways and has the option to convert that value to something other than points. I suspect the problem was a misuse of sscanf (long scanResult = sscanf(str.c_str(), "%lf%[a-z]%lf", &n, s1, &n2);).

I'll post it here if others want to see it (forewarned of hidden issues) and you feel it's appropriate to do so.


RE: callbacks that stop calling back - Rick Johnson - 01-29-2021

(01-20-2021, 01:03 PM)garrett Wrote: Pushing and popping context is required whenever your plugin is messaged through any other means than via Illustrator directly; which is to say, if your PluginMain() function (which hdi_core abstracts away so you don't have to deal with it) is NOT called, then you have to push context if you want to interact with Illustrator and pop context when you're done interacting with Illustrator. An example of this is when the OS itself messages your plugin, perhaps in response to e.g. some event in a custom widget you have created completely from scratch, or in response to a timer you registered directly with the OS, or response to your interacting with a third-party library that later calls your code of its own accord.

I think I have the situation you described. In a custom art update callback, I call a function in a library I created (separate file with its own namespace) to manipulate art. It accepts a reference to an art (in my case an aiArtHandle) and returns a group containing the original art with transformations, along with new art. It works fine when called from a menu or button, but as part of a custom art update callback, it fails. For now, calling uid()->name() on art the plugin creates works for a while, then after a few for loops, it crashes, suggesting that art has moved in memory.

So I modified the custom art update callback like this:

Code:
HDI_CORE_ILLUSTRATOR->pushContext();
AIArtHandle newArt = myLib::xform::xformArt(thisArt->aiArtHandle(), someValue);
HDI_CORE_ILLUSTRATOR->popContext();

I tried it with and without a return value, thinking it might pause the update thread until the library was finished, but that didn't make a difference. I'm SO close on finishing this. Any suggestions would be very much appreciated.


RE: callbacks that stop calling back - garrett - 02-03-2021

If you, or the library, are doing things with Illustrator data (which it sounds like, since art certainly falls under this category) in a thread other than the "main" thread you are far more likely to run into issues like this. Illustrator is not intended for multi-threading, so perform all document/art/etc. tasks in the main thread.


RE: callbacks that stop calling back - Rick Johnson - 02-20-2021

It was a long haul to track this down, but I'd like to report some success.

I moved all functions that manipulate art into the main file (now over 1,400 lines!). That didn't help. Adding or removing pushContext and popContext in the custom art update callback made no difference, either.

Here's what was happening. While evaluating a path to create a group of multiple paths, several Art objects contain partial duplicates of the original path. A loop essentially moves the path along an assembly line, where it's evaluated segment-by-segment. Art is assigned from one Art object to another (e.g., oldArt = newArt; then newArt created again). I don't know if this reassigning set up a problem situation, but I suspect it's possible.

Sometimes an art object is no longer needed and is disposed. All is well when the function is called from a tool or menu, but when called from a custom art callback I saw something like this:

someArt.artType(); // returns 110
someOtherArt.dispose();
someArt.artType(); // now returns 0
someArt.isEmpty(); // returns 0 -- some operations work, but others cause a crash

My solution was to store references to the junk art in a vector, then delete all junk at the end of the function.

I hope this is helpful to others.


RE: callbacks that stop calling back - Rick Johnson - 07-07-2021

(01-20-2021, 01:03 PM)garrett Wrote: Pushing and popping context is required whenever your plugin is messaged through any other means than via Illustrator directly; which is to say, if your PluginMain() function (which hdi_core abstracts away so you don't have to deal with it) is NOT called, then you have to push context if you want to interact with Illustrator and pop context when you're done interacting with Illustrator. An example of this is when the OS itself messages your plugin, perhaps in response to e.g. some event in a custom widget you have created completely from scratch, or in response to a timer you registered directly with the OS, or response to your interacting with a third-party library that later calls your code of its own accord.

I think I understand this, but need to make sure: When notifiers and key press monitors are registered with hdi::core::Dispatcher, then returned to my plugin through its callback, do I still need to push and pop context?

I have a few custom widgets, but they all work entirely through callbacks set within the hdi::core::CustomWidget class when the widget is created in my post-startup event. I've assumed that these don't need to push or pop context, either.

Also, custom art receives update events not necessarily from the plugin, but from Illustrator, so it seems push/pop context should not be needed there, I believe.

I would think an example of an external event in need of push/pop would be if I created a hook for a JavaScript, and that would require manually pushing and popping the context. Right?

Thanks a ton in advance. :-/


RE: callbacks that stop calling back - Rick Johnson - 07-09-2021

(02-03-2021, 01:12 AM)garrett Wrote: If you, or the library, are doing things with Illustrator data (which it sounds like, since art certainly falls under this category) in a thread other than the "main" thread you are far more likely to run into issues like this. Illustrator is not intended for multi-threading, so perform all document/art/etc. tasks in the main thread.

I'm not sure how to control which thread things go to, but I'm guessing I have three of my own.


Code:
gxGlobals myGlobals;
gx::About *myAbout;
gx::gxPrefs *myPrefs;

At the top of the main file, I declare some suites imported from the SDK, as well as three classes.

The globals class is created locally, so I believe that is part of the "main" thread.

The About Box and preferences are created at startup with "new" so may or may not have their own thread. (?) About just does dialog boxes, but the gxPrefs preferences class works with the document dictionary.

I also have several libraries included in the main plugin cpp file that use their own namespaces, but I hadn't expected that those unique namespaces would have anything to do with what thread they run in.

Am I on the right track? It's probably much more complicated than this. I'm doing my best studying books and online resources, but not sure how unique the Illustrator API + CORE environment is compared to generic c++.