0

In my plugin, I create a thread (using pthread in my case) to listen to external event. When event occurs, I want to communicate back to JavaScript. As far as I understand, I can only call NPN_* method in the plugin thread. As the result, I will need to utilize NPN_PluginThreadAsyncCall in my thread to call other NPN_* method for JavaScript communication. So a simple flow is

The problem I am facing now is, if the external occurs consecutively, for example, 2 events with different data input, I will receive the same data twice in the callback sometimes (in half of the time two different data is returned). I guess it's because the NPN_PluginThreadAsyncCall is an async call, when two consecutive events call back, NPN_PluginThreadAsyncCall is invoked twice, the data is overridden by the 2nd call already before callback to JavaScript for the 1st event actually occurs.

Initially, the event data I want to return is a global variable. But I also tried to change it to a local variable, it did not seem to help. Is there any other way I can make my code a sequential call to talk to JavaScript?

I have done some research and found this, How to callback plugin thread on Safari 5.1 on OSX?. But I still don't quite understand (I am working on Windows).

Community
  • 1
  • 1
Dino Tw
  • 3,167
  • 4
  • 34
  • 48

2 Answers2

3

It sounds like you are simply overwriting data (in the case that two events occur before the async call for the first could be handled).

There are two ways you could approach this:

  • use the userData parameter of NPN_PluginThreadAsyncCall to pass your data around
  • use a thread-safe container (e.g. std::list or queue protected by a mutex) to store the event data (event puts the data in, the async handler retrieves and processes it)

The question you linked is for a different problem where NPN_PluginThreadAsyncCall is not available or not working.

Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
  • Thank you for the hint. I already tried your suggestion 1 (using local variable as mentioned), but it did not seem to help. I will look into the suggestion 2. Yes, I know the link is not directly related. But I was hoping to the workaround would resolve my problem, and did not quite understand the solution. I will post my solution if one is found later. – Dino Tw Jul 06 '12 at 19:52
  • @dino: What exactly do you mean by using a local variable? Are you trying to pass a pointer to a function-local variable through NPN_PluginThreadAsyncCall? That wouldn't work as it would go out of scope, you'd need to pass e.g. a dynamically allocated object through userData. – Georg Fritzsche Jul 07 '12 at 00:09
  • yes, it did not work. I thought I would need to deallocate the object I created, and was wondering weather NPN_PluginThreadAsyncCall would spawn separate threads when called, so I tried to pass the local variable to NPN_PluginThreadAsyncCall in the event callback function. – Dino Tw Jul 09 '12 at 17:46
  • And your 2nd hint is very helpful. When I started to think about using the container for my need, all of the sudden I felt it was really stupid of me, using queue abstract should fix my problem. And because push is always called before pop, I don't have to worry about thread-safe. I tried the implementation, so far so good. Thank you so much for the great hint. – Dino Tw Jul 09 '12 at 18:00
  • @dino: Good to hear it works for you. Keep in mind that unless the system event calls are only occuring on the main thread, you can still run into issues with concurrent access on the shared container. – Georg Fritzsche Jul 11 '12 at 07:16
  • I ready somewhere saying npapi plug-in has only one main thread. Although I am not very sure yet, the container implementation works fine so far. I will try to use a script to generate more events to verify the code. Hopefully it will still work fine. – Dino Tw Jul 12 '12 at 00:45
  • @dino: You can run as much threads in a NPAPI plugin as you want, but all `NPN_*` calls except `NPN_PluginThreadAsyncCall` have to occur on the browser thread (i.e. main thread). You could verify whether the events you get are occuring on the main thread by e.g. breaking on them from a debugger and checking from there - if they are then you need no synchronisation mechanisms. – Georg Fritzsche Jul 12 '12 at 17:36
  • it's good to know the a npapi plugin can run on multiple thread. And it's also good you mentioned that I could use break point for debugging. But I am wondering how I can do it on a dll? For a application, I know how it works. But on a dll, will the code just stop at the break point I set. I remembered I tried it before, and it did not work. Maybe I missed something. – Dino Tw Jul 13 '12 at 21:58
  • @dino: DLLs get loaded into the host process, so you must attach the debugger to that. Firebreath has a [page on debugging](http://www.firebreath.org/display/documentation/Debugging+Plugins) that should help. – Georg Fritzsche Jul 14 '12 at 17:30
  • The tutorial on Firebreath seems to be easy to follow, I will try it later. Thank you so much for the information. – Dino Tw Jul 15 '12 at 19:55
0

You could implement this as a mutexed std::deque, where the first inserted data is the first that you pop.

Just make sure that you don't push or pop at the same time (use mutexes). That's what I use in my plugin :)

Gui13
  • 12,993
  • 17
  • 57
  • 104
  • No need for a `deque` if only FIFO is required, a `queue` is sufficient. – Georg Fritzsche Jul 06 '12 at 15:54
  • Hi Gui, yes, that's the approach I used. It seems to resolve my problem so far. I am not so familiar with the C++ lib yet, so I followed Georg's suggestion by using std:list. Luckily, it has push_back, front, and pop_front functions to implement FIFO. And also thank you for sharing your experience :) – Dino Tw Jul 09 '12 at 17:57
  • I don't have enough reputation to do so yet :( I have no idea why your answer has a -1 in the front, and I am not able to click on up arrow to change it. – Dino Tw Jul 10 '12 at 21:09
  • No pb, I don't care :) I guess it's because I answered after Georg. – Gui13 Jul 11 '12 at 06:36
  • Thanks for the great help from both of you :) – Dino Tw Jul 12 '12 at 00:45