cnr-isti-vclab / PyMeshLab

The open source mesh processing python library
GNU General Public License v3.0
765 stars 62 forks source link

Shape Diameter Function Crashing Python #133

Open fortoboy opened 3 years ago

fortoboy commented 3 years ago

Hello,

I was able to reproduce this in Python 3.8.8 on my MacOS 11.5 as well as Google Colab. Trying to run the Shape Diameter Function crashes the kernel using any mesh. For example:

import pymeshlab ms = pymeshlab.MeshSet() ms.load_new_mesh('brain.ply') ms.shape_diameter_function() ms.save_current_mesh('test.ply')

brain.ply.zip

I found reference to this issue in the comments of a blog: http://3dgraphicsprogramming.blogspot.com/2011/07/gpu-accelerated-shape-diameter-function.html

Also when I run it through my terminal i do get an error message that may be helpful: bjc[22035]: Class RunLoopModeTracker is implemented in both Python 3.8.8 (default, Apr 13 2021, 12:59:45) [Clang 10.0.0 ] :: Anaconda, Inc. on darwin Type "help", "copyright", "credits" or "license" for more information.

import pymeshlab ms = pymeshlab.MeshSet() ms.load_new_mesh('brain.ply') ms.shape_diameter_function() objc[22035]: Class RunLoopModeTracker is implemented in both ~/opt/anaconda3/lib/python3.8/site-packages/pymeshlab/Frameworks/QtCore.framework/Versions/5/QtCore (0x102ed5288) and ~/opt/anaconda3/lib/libQt5Core.5.9.7.dylib (0x119d4aa80). One of the two will be used. Which one is undefined. zsh: abort python3

alemuntoni commented 3 years ago

Hi, It seems that the Qt libraries contained into the pymeshlab package are conflicting with some other Qt libraries (different versions) installed into your machine. Looking to this similar issue, it seems that installing through pip in a conda environment breaks the package, and probably it is happening the same here with pymeshlab. I don't have a real solution to this issue right now, but just making sure to install pymeshlab in a clean non-conda environment should be ok. A solution could be having a pymeshlab conda package, but at the moment we don't plan to release it.

alemuntoni commented 3 years ago

Just to be double check: does this issue happen just when calling the filter shape_diameter_function, or it also happens when calling other filters?

fortoboy commented 3 years ago

Thank you for the advice. And to answer your question, just the shape_diameter_function. The convex hull function worked great.

On Wed, Aug 18, 2021 at 12:19 PM Alessandro Muntoni < @.***> wrote:

Just to be double check: does this issue happen just when calling the filter shape_diameter_function, or it also happens when calling other filters?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cnr-isti-vclab/PyMeshLab/issues/133#issuecomment-901248982, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJLHDFP6XYE5GU25IO73QLT5PMQ7ANCNFSM5CEGQGYQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

alemuntoni commented 2 years ago

Ok, it seems that it cannot use filters that require opengl context (another filter that should crash should be ambient_occlusion). It's very hard to replicate and try to solve the issue, since it seems that happens only on particular system configurations...

Freakaz0id commented 2 years ago

I ran into the same problem recently. The shape_diameter_function crashes the shell, when executed inside a docker container running miniconda.

If you are interested in replicating, here's a Dockerfile

FROM ubuntu:20.04

RUN apt-get update

# Add environment variables
ENV PATH="/root/miniconda3/bin:${PATH}"
ARG PATH="/root/miniconda3/bin:${PATH}"

# Install Miniconda with Python 3.8
RUN apt-get update -y \
    && apt-get install -y wget && rm -rf /var/lib/apt/lists/*
RUN wget \
    https://repo.anaconda.com/miniconda/Miniconda3-py38_4.10.3-Linux-x86_64.sh \
    && mkdir /root/.conda \
    && bash Miniconda3-py38_4.10.3-Linux-x86_64.sh -b \
    && rm -f Miniconda3-py38_4.10.3-Linux-x86_64.sh
RUN pip install pymeshlab

RUN apt update
RUN apt install libopengl0 -y
RUN apt install libglu1-mesa-dev -y
RUN apt-get install libglib2.0-0 -y

CMD ["bash"]

When you build the image, start the container, enter it and start python...

docker build -t pylab .
docker run -d -dit --name pylab pylab
docker exec -it pylab bash
python

You can try running the shape diameter function

import pymeshlab
ms = pymeshlab.MeshSet()
ms.apply_filter('dodecahedron')
ms.shape_diameter_function(onprimitive='On Faces')

Which will lead to the python shell crashing.

Note, that I had to install libopengl0 and libglu1-mesa-dev manually, because otherwise pymeshlab cannot be imported. Maybe some other libraries are missing as well?

ImportError: libGL.so.1: cannot open shared object file: No such file or directory
ImportError: libglib-2.0.so.0: cannot open shared object file: No such file or directory
...
Freakaz0id commented 2 years ago

What I found out is, that this bug can happen for two different reasons:

a) Missing dependencies:

I could not figure out which exact libraries are responsible, because the error message is not giving any details. I think this is a problem with the original meshlab code, because it is not raising exceptions when a library is missing, so it cannot be forwarded to python. I assume it just sends the message Aborted followed by an exit code, which terminates the whole process including python. This is really bad, because it is not only crashing the function, but the parent shell as well! This means it cannot be catched via try-except! and should be fixed ASAP!

A quick-and-dirty workaround is to install meshlab itself, because it comes with all libraries that pymeshlab may requires. But sadly it also installs many libraries, that it does not need and also an unwanted python3 environment :(

apt-get install meshlab

I would really like to narrow it down, but I don't know where to even start.

b) Missing OpenGL context

As I understand it, OpenGL functions and Qt applications require a so called OpenGL context to hook into a (hidden) window, even if nothing is displayed. Which is a bummer, if you want to run said application or function inside a container or Raspberry Pi, which do not have a screens. I am not sure how you would manage on Mac or Windows, but on Linux you can create a virtual framebuffer, which emulates a screen using xvfb:

apt-get install xvfb -y

export QT_DEBUG_PLUGINS=1
export QT_QPA_PLATFORM=xcb
export QT_QPA_PLATFORM_PLUGIN_PATH=/opt/Qt/${QT_VERSION}/gcc_64/plugins
export QT_PLUGIN_PATH=/opt/Qt/${QT_VERSION}/gcc_64/plugins
export DISPLAY=:1

However, the screen has to be activated, before you the function/app. So you have to execute the following on startup (or ENTRYPOINT in docker):

Xvfb :1 -screen 0 1024x768x16 &

When importing a pymeshlab, it should check if all required libraries are present and also if there is a display available to mount into (and create a virtual one, if there isn't).


EDIT: Mounting a virtual frame buffer can also be achieved using the xvfbwrapper package: https://github.com/cgoldberg/xvfbwrapper

import pymeshlab
from xvfbwrapper import Xvfb

vdisplay = Xvfb()
vdisplay.start()

try:
    ms = pymeshlab.MeshSet()
    ms.apply_filter('dodecahedron')
    ms.shape_diameter_function(onprimitive='On Faces')
finally:
    vdisplay.stop()
alemuntoni commented 2 years ago

This is really bad, because it is not only crashing the function, but the parent shell as well! This means it cannot be catched via try-except! and should be fixed ASAP! A quick-and-dirty workaround is to install meshlab itself, because it comes with all libraries that pymeshlab may requires. But sadly it also installs many libraries, that it does not need and also an unwanted python3 environment :(

There is not much I can do here, unfortunately. We use linuxdeployqt to make the pymeshlab package "self-contained" (the same that we use to make appimages). If there are still libraries that are not bundled, it is because they are system libraries that change between distros. And, as far as I know, there is no way to be sure that libraries are installed in the system from python.

Anyway, note that the issue about libopengl.so missing should have been solved in the last version of pymeshlab, since only LibGL is required and it is bundeld in the pymeshlab package.

About the missing screen, I could try to detect in some way if one exists (I don't know if there is a standard way to do this in C++) and then raise an exception when a filter that requires opengl is run.