Very Strange Behaviour when Forking into libVLC - fork

I have an app which is built with libVLC, accessing the standard installed libvlc-dev libraries, plug ins, headers etc on Ubuntu Linux.
My app generally works perfectly, and its mostly there to receive UDP streams and convert to something else.
However, I am having a really weird issue in a specific mode, and so far I have invested around 30 development hours in trial and error trying to solve it - and I am hoping some VLC genius here can unlock the puzzle.
It revolves around http:// based URL sources. Typically for HLS, but the same issue happens with any http based source.
IMPORTANT: If I launch my app in terminal, everything works perfectly (including http streams). However, if I 'sublaunch' the same app with the same launch parameters from my parent process using fork() and then execv(), it fails to play any http based streams (although things like UDP do still work perfectly).
I have checked the obvious things like ensuring the VLC_PLUGIN_PATH is set correctly, and I have exhaustively compared all other environment variables in the 2 launch states, without finding anything obviously related.
After enabling full logging, I can see there is a glaring difference during the url opening process - and it seems something is amiss when evaluating plug in suitability.
In Terminal Launch:
looking for access_demux module matching "http": 20 candidates
no access_demux modules matched
creating access: http://...snip....myfeed.m3u8
looking for access module matching "http": 28 candidates
resolving ..snip....myfeed
outgoing request:
and the stream plays fine
However, when forked, and execv, I see the following:
looking for access_demux module matching "http": 40 candidates
no access_demux modules matched
creating access: http://...snip....myfeed.m3u8
looking for access module matching "http": 56 candidates
and it sticks right there and does not ever even make an http call out.
Of course the odd thing which I hope may be a clue is that the forked environment finds twice as many candidates when matching. However, it fails to complete the http access stage, and goes no further.
This is driving me crazy, and I have given up 5 times so far, only to come back for another try. However, I have exhausted what I can discover via logging, and I am really hopeful a VLC developer here might be able to point me in the right direction.
Many thanks for any ideas, tips, gut instincts or whatever.
Thanks !

SOLVED: In the parent app, we happen to be calling: signal(SIGCHLD,SIG_IGN); at some point before the fork(). (so this is inherited by the child presumably) In this condition when forked and execved libVLC cannot work with http sources. There must be some behaviour which relies on SIGCHLD in VLC's http handling. We could solve the problem either by removing signal(SIGCHLD,SIG_IGN); from the parent, or by adding signal(SIGCHLD, SIG_DFL); to the child libVLC app. Once we do this, libVLC behaves as expected.

Related

What exactly happens when we disable history in Firefox?

I have a problem with live video streams in the system I am developing that happens only in Firefox and only in normal mode.
The player correctly loads the stream, but after a few seconds can't continue to load and just keeps trying and trying forever.
This doesn't happen in Chrome, nor if I load the page in Private Mode, nor with normal videos. Just with live streams, just in Firefox, just in normal mode.
This happens both in local development (home, remote connection) and in the corporative cloud.
It's an Angular 8/NodeJs system and the player I use is Clappr. I changed to Video.js and the problem continued.
The stream is coming from a load balancer with 6 children servers, each one with an apache server who have a proxy to an icecast server that originates the stream.
[load balancer] < [6 child servers with apache server proxy] > [icecast server]
I work for a very large company that has an IPS system installed. It was the first thing I thought. But the IPS team could not find any blocked traffic. Also if it was that, why would the traffic not be blocked in private mode?
So I thought about trying to pinpoint what the exact configuration is different in private mode that does the trick and I figured out that disabling all history (not only navigation and downloads or forms) makes it work too.
Does anyone knows what exactly happens when the navigation history is disabled? Besides not saving history, does it have an impact on something else? Some type of cache, network or something like that? Anyone has any idea about how to make stream work without disabling history? I can't ask my users to disable history just to use my system.
EDIT
One thing that may be relevant to the issue is that in Firefox it doesn't show LIVE label when the transmission starts. It shows a negative number. Maybe this could create some problem with the history.
I couldn't find the information on what exactly happens when we disable history in Firefox, but I could solve the problem of playing the stream in Firefox, so I won't accept this answer, but leave it here for future reference in case someone has a similar problem.
I solved it by adding ?nocache=<random integer of length 10> to the video url. Please notice that if you already have some parameter in your url, you can't have 2 ? characters in your url and have to mix parameters correctly.

Streamlink with Youtube plugin: How to get scheduledStartTime value?

I am using Streamlink to help some of my technically challenged older friends watch streams from selected sites that webcast LIVE two or thee times a week and are ingested into Youtube. In between webcasts, it would nice to show the User when the next one will begin via the apps Status page.
The platform is Raspberry Pi 3 B+. I have modified the Youtube plugin to allow/prohibit non-live streams. If '--youtube-live-required' is in the command line, then only LIVE streams will play. This prevents the LIVE webcast from re-starting after it has ended, and also prevents videos that Youtube randomly selects, from playing. I have also applied a 'soon to be released' patch that fixes a breaking-change that Youtube made recently. I mention these so you know that I have at least a minimal understanding of the Streamlink code, and am not looking for a totally free ride. But for some reason, I cannot get my head around how to add a feature to get the 'scheduledStartTime' value from the Youtube.py plugin. I am hoping someone with a deep understanding of the Streamlink code can toss me a clue or two.
Once the 'scheduledStartTime' value is obtained (it is in epoch notation), a custom module will send that value to the onboard Python server, via socketio, which can then massage the data and push it to the Status page of connected clients.
Within an infinite loop, Popen starts Streamlink. The output of Popen is PIPEd and observed in order to learn what is happening, and then sends that info to the Server, again using socketio. It is within this loop that the 'scheduledStartTime' data would be gleaned (I think).
How do I solve the problem?
I have a solution to this problem that I am not very proud of, but it solves the problem and I can close this project, finally. Also, it turns out that this solution did not have to utilize the streamlink youtube.py plugin, but since it fetches the contents of the URL of interest anyways, I decided to hack the plugin and keep all of this business in one place.
In a nutshell, a simple regex gets the value of scheduledStartTime IF it is present in the fetched URL contents. The Hack: That value is printed out as a string 'SCHEDULE START TIME:epoch time value', which surfaces through streamlink via Popen PIPE which is polled for such information, in a custom module. Socket.io then sends the info to the on-board server, that sends a massaged version of the info to the app's Status Page (Ionic framework, typescript, etc). Works. Simple. Ugly. Done.

Best practice for updating Go web application

I am wondering what would be the best practice for deploying updates to a (MVC) Go web application. Imagine the following scenario :
1) Code and test some changes for my Go Web Application
2) Deploy update without anyone currently using the previous version getting interrupted.
I don't know how to make sure point 2) can be covered - when somebody is sending a request to the server and I rebuild/restart it just in this moment, he gets an error - even if the request just uses a part of the code I did not touch or that is backwards-compatible, or if I just added a new Request-handler.
Maybe I'm missing something trivial or a well-known pattern as I am just in the process of learning go and my previous web applications were ASP.NET- or php-applications where this was no issue as I did not need to restart the webserver on code changes.
It's not just an issue with Go, but in general we can divide the problem into two separate ones:
Making sure current requests do not get terminated and affect user experience.
Making sure there is no down-time in which new requests cannot be handled.
The first one is easier to tackle: You just don't violently kill your server, but tell it to exit, causing a "Drain phase", in which it does not accept new requests and only finishes the currently running requests, and exits. This can be done by listening on signals for example, and entering the app into a special state.
It's not trivial with Go as the default http server doesn't support shutting it down, but you can start a server with a net.Listener, and then keep a reference to it an close it when the time is due.
Now, doing only approach one and then starting the service again will cause new requests not to be accepted while this is going on, and we all know this can take a number of seconds in extreme cases.
So what we need is another instance of the server already running with the new code, the instant the old one is not responding to new requests, right? That can be done in several ways:
Having more than one server, and a load-balancer on top of them, allowing one (or more) server to take the load while we restart another. That's the simplest way, and the way most people do it. If you need N servers to take the load of your users, just keep N+1 and restart one at a time.
Using socket sharing tricks. In Newer Linux kernels, Many processes can listen and accept on the same port. What you do is simply start the new instance and then tell the old one to finish and exit. This way there is no pause. This is done by setting SO_REUSEPORT on the listening socket.
The above can be automated with ready to ship solutions, like Einhorn, that deals with all the details for you, see https://github.com/stripe/einhorn
Another approach is documented in this blog post: http://blog.nella.org/?p=879

Is it possible to use IPC inside of a IE8 Browser Helper Object?

I need to communicate with a Service using IPC from inside of a Browser Helper Object (registered with IE8). Unfortunately, all of this communication is done through an Assembly API that I have no control over. Whenever this API starts up I get the following error:
ExceptionSystem.Runtime.Remoting.RemotingException: Failed to connect to an IPC Port: The system cannot find the file specified.
I realize that it is difficult to discern what the issue is without source. However I am curious if anyone knows of anything sort of permissions or DLL issues that would prevent IPC from working in this case.
It looks like this issue can be caused by a number of things.
UAC, as always, can be an issue and should be disabled to make sure it isn't causing problems.
The other issue is that IE allocates a process for the main frame as well as individual tabs. This means that there is no guarantee that your BHO is in the main frame process. If you set the following registry key, IE will prevent the browser from allocating extra tab processes:
[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main]"TabProcGrowth"=dword:00000000
In general, neither of these solutions are ideal though. I ended up backing away from this entire attempt as it seems very problematic from a number of angles.

What is the framework/function used in Cocoa for detecting machines

I'm trying to get a listing of machines in my local domain, specifically ones running a administrative web service (_asip-webadmin). I've been fooling with NSNetService but it would seem that it's only good for Bonjour listings (as I can trap them just fine). I've tried something along the lines of:
[mySearch searchForServicesOfType:#"_asip-webadmin._tcp." inDomain:#"local."];
which results in utter failure, or should I say the debugger gives me a blank stare back. A point in the right direction is all I need. Thanks!
I was on the right track. The problem was I was using the wrong service name.
I mistakenly looked in etc/services for the service name, whereas I should have looked here:
http://www.dns-sd.org/servicetypes.html
The following line does work for what I needed:
[mySearch searchForServicesOfType:#"_servermgr._tcp." inDomain:#"local."];
Assume mySearch is of type NSNetServiceBrowser.

Resources