We are running a GStreamer based pipeline inside balena including the hot-plugging of cameras. The container is based off balenalib and the hot-plugging part works fine with devices showing up inside the container.
GStreamer has the gst-device-monitor-1.0 -f command, which can list the current audio video devices connected as well as continuously listen on changes to the devices
The command uses the libgudev library (glib binding to libudev) to listen on udev device changes, which it then filters and acts upon.
Outside of a container this works perfectly fine. Whenever a camera is plugged in while gst-device-monitor-1.0 -f is running, it prints information about the device.
Inside the container running gst-device-monitor -f will correctly identify and analyse all currently connected devices, but it will not monitor devices as they are plugged in. Re-running it after plugging in new hardware will also work as expected.
Directly monitoring the udev events using udevadm monitor inside the container works fine.
This can be reproduced by building the following image:
@wolvi-lataniere Can you test the C example code in a balenalib based container that runs with UDEV=1 ? I just wonder if there is a conflict between udev and udevd when applying your suggestions to a balenalib image running udevd.
Thanks for the feedback.
About Focal vs Bionic, I would recommend going for the newest version whenever possible as end of life can come pretty quickly considering a standard development/deployment cycle.
As you can see here Bionic will stop receiving software update in the next 12 months. For newer development I would recommend using the latest available LTS (Currently for Ubuntu it is Jammy) to spare you some maintenance work in the near future.
I will have a look at a build with bionic to see if I can figure it out.
I looked into it and the fix I proposed doesn’t work on bionic.
I managed to get the code working without starting the udev service first, but I had to use network_mode: "host" in order to allow your udev_monitor_new_from_netlink(udev, "udev"); function to grab the host netlink.
But after restarting the udev service we are stuck in a constant loop of devices being registered and unregistered. That holds for the solution by @bversluijs as well as what @wolvi-lataniere suggested.
Still stuck at this I’m afraid.
It is not enough to make the UDEV restart from within docker-compose.yml cmd’s.
This tricked me also!
You have to add the “restart” cmd into a separate start.sh file that will execute prior to your container-startup.
Inside docker-compose.yml of your service at question, add the following:
COPY start.sh /opt/
# We are running our entrypoint commands through the start.sh script
CMD ["bash", "/opt/start.sh"]
(i.e. in our case the root folder is /opt (in your case it might be a different folder)…
And the start.sh script looks as follows:
if which udevadm >/dev/null; then
echo "Restarting UDEV Service to enable hotpluging"
set +e # Disable exit on error
service udev restart
set -e # Re-enable exit on error
echo "UDEV Service restarted"
echo "Starting MyContainer Service"