-
Notifications
You must be signed in to change notification settings - Fork 182
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
macOS: problems with Java AWT::Robot and AWT::Event-Queue (window not displayed, hangs waiting for events to finish) #911
Comments
Thanks. This is definitively something in the path towards fixing it. So the path forward on this is I need to go to the travel department and pickup a loner OSX laptop and set up a development. Unfortunately, there few logistical problems with that plan. First I am not allowed on site to get to travel to due to COVID 19. Next I suspect travel is currently closed down due to COVID 19. Second being December finding someone who knows how to resolve those issues means the soonest I will be able to work on this will be in January. |
@Thrameos |
Unfortunately this is the sort of problem that I would need to do a fair amount of exploring. It is only obvious in retrospect after you find a series of cases that succeed or fail that you can find the documentation that points to the source of the problem. |
@Thrameos |
Okay I vaguely recall seeing some information on this. The problem is that Java and AppKit have two separate requirements. Java wants to handle events on a separate event handler thread, but AppKit wants to handle all events on the Appkit main thread. When you start Python, you are almost always running on the main thread (of Python) which may be the AppKit main thread. Thus only that thread can handle events. This runs into a serious problem. You want to keep running on the Python thread, but then you can't service events. To handle this broken situation you would need to transfer control and start running Python on a different thread and tell the main thread to service the events. Even if the Python main is not the Appkit main, the appkit main thread is most certainly already started by Python when Java starts. So now Java is going to start its event thread in a different thread than the current AppKit thread and well we are headed for another deadlock. They gave some code to "help" with this issue, but if the Python main is already the Appkit main there is no real way to tell Python to continue execution starting from this line in the code for things like interactive programming, this is always going to be a weak point. It is not clear that the Python main thread has to be the Appkit thread, but I don't know enough about the API to determine that. https://wiki.openjdk.java.net/display/MacOSXPort/Java+vs.+AppKit+Threading+Manifesto Unfortunately not having a Mac there isn't a lot a can do to develop a better solution and this weakness is likely to cause issues for the future. We really need and expert to guide us on how to get this to work. |
Not sure it this information helps. It seems to be indicating that we need to add an enter and exit section to our JNI calls to work with AppKit. There are only a handful of JNI incoming calls from Java. The most notable being JProxy call back hook. There are others on the factory hooks, but those are not very likely to be able to stall unless the user plugs something horrible into the class creation routines. If someone wants to contribute by adding some of these blocks and seeing if it helps with the deadlock it would be appreciated. I am not sure it is the right path, but perhaps it will help. Edit: These may be pointlessly out of date as most JNF comes up with references from 10 years ago. |
http://mirror.informatimago.com/next/developer.apple.com/technotes/tn2005/tn2147.html
Again not sure if this applies to our Python/Java model. Assuming it does we would need to start Java in a different thread than main then attach the Pythons main thread as a daemon thread. This is likely to cause issues with our shutdown model, though perhaps there is a way to handle it because if Python is a daemon thread it won't count toward the shutdown. |
Very good findings. But this means IMHO, that the approach of JPype in macOS only works with Java stuff, that does not use any AWT/Event-Loop features. Hence JPype -> SikuliX will not work on macOS, until someone finds a solution based on the above mentioned evaluations (sorry, but I am not one of those someone's). I will continue to watch the further development in this problem area of JPype. |
Assuming this is actually is the issue, there are two approaches.
I am going to assume that option 1 is a poor one and examine the changes that result from option 2. The user visible changes required for the second option is
The other change is jpype/gui would need to be deprecated. It was not documented and I am not aware of any users, but once we make this structure change it may interfere or confuse. The consequences for existing JPype using projects would be minimal. Some would require adding I can likely make these structural changes without actually having access to an OSX machine, but there is little way can actually debug it enough to know if it fixes the osx issues until I gain access, so unless someone volunteers to be a guinea pig I should likely place this on the wishlist for now and start work once I can access an osx machine. @marscher The proposed changes are structural in nature and likely have at least some consequences from the user prospective even if I keep it minimal. If you have some direction on the path to take, it would be appreciated. We have had a lot of traffic on OSX users here so I am guessing interest is relatively high. But if you think I have overlooked something on the user prospective, then I should adjust the plans. |
@Thrameos |
Sure thing. Right now I am just debating the priorities for this particular task relative to others. My main large tasks appear to be
The order that I complete these tasks will have a large influence on the final product. If I have the reverse bridge then how I accomplish the other tasks may be very different than if I proceed in the opposite order not to mention the potential time that a solution may be available. The reverse bridge is the largest of the tasks in terms of scope, but it also simplifies all other tasks which complicates the decision process. I will think this over and get back to you when I have defined a path. |
@Thrameos Feel free, to delete this remark: |
Py4j is intended for a different audience than JPype. It exists to create an RPC like connection between Python and Java. I often encourage projects that require a transient transactional type connection rather than a highly integrated one to use Py4j. Both approaches have their strong points and weak points. |
Since I am one of the JPype users that would be interested in a solution for this macOS issue, I would like to let you know that in the last five years I was using SikuliX with Robot Framework with the single available solution of Remote Server and XML-RPC protocol. Since this method is slow, I had to start the server once before any test run, and close it after, although on web testing this is not the most important thing to do. The ideal solution is that all tests are independent of each others and there should be no need to start e.g. a remote server just to be able to use a certain library when needed. For that reason I was lately proposing a new Python library (robotframework-sikulixlibrary) that is working great on Windows (also tested on Linux), much more advanced than with XML-RPC protocol so I am very happy to use it also in the future, and to suggest it also to other Robot Framework SikuliX users. For us, the other alternative would be e.g. image libraries built on top of pyautogui, but it seems these libraries are quite limited when compared with SikuliX :) |
@adrian-evo |
@RaiMan |
This one is still waiting for access to an OSX machine. I believe the solution would be to spawn JVM in a separate thread and then use a message to kill it on shutdown rather than keeping the main JVM thread and main Python thread the same. This may have interactions with the shutdown sequence. For symmetry we would want to use this same path for windows, osx, and linux otherwise we may end up with different shutdown behavior on different systems. This fix would require porting enough os specific threading libraries so that we can create a thread, signal it to terminate, and join it after. We also may need to add a "gui" option which informs JPype that it should also launch an appkit thread. Unfortunately, I can't really complete this work until I am able to replicate it locally. |
This might be related to #906
My findings are when trying to use SikuliX through JPype on macOS.
On Windows and Linux it seems to work as reported by other users.
Find the issue doc here: RaiMan/SikuliX1#400
For my plans
Python-to-SikuliX
I will ignore JPype, until this problem area is fixed in Java.The text was updated successfully, but these errors were encountered: