Infinite loop in libcppnetlib-uri.so causing 100% CPU usage

Server Version#: 1.15.3.876
Player Version#: N/A

There appears to be an infinite loop in boost::network::uri::detail::parse as called from libcppnetlib-uri.so.

Building a 0.13.0 of cpp-netlib and placing the resulting libcppnetlib-uri.so in the lib directory solves the problem. I’m not sure if it’s a boost issue or a cpp-netlib issue.

The backtrace is too large to include in the message, but the weirdest thing in the backtrace is the 26919 character line that starts like this:

#6 0x00000008027d89b6 in bool boost::fusion::detail::linear_any<boost::fusion::cons_iterator<boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const> >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::plus<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::1::char_traits, std::1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::nil> > >, boost::fusion::nil> > > > > > > > > const>, boost::fusion::cons_iterator<boost::fusion::nil const>, boost::spirit::qi::detail::alternative_function<std::__1::__wrap_iter<char const*>, boost::spirit::context<boost::fusion::cons<std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator >&, boost::fusion::nil>, boost::fusion::vector0 >, boost::spirit::unused_type, boost::spirit::unused_type const> >(boost::fusion::cons_iterator<boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const> >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::plus<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::raw_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::kleene<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > >, boost::spirit::qi::exact_iterator >, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>, std::__1::basic_string<char, std::__1::char_traits, std::_1::allocator > (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> const>, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::literal_string<char const (&) [3], true>, boost::fusion::cons<boost::spirit::qi::repeat_parser<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<std::__1::__wrap_iter<char const*>

Before even considering this is a real issue I suggest updating to a more recent build.

Also you don’t have debug symbols (its not a debug build) so a backtrace might not even offer any help in case there’s actually an issue somewhere.

Regardless the best advice I can give is update, check if you still have 100% cpu usage and submit logs.

Updated to 1.15.6.1079, confirmed issue is still present.

Attaching two sets of logs… plex-BadLogs.zip is as distributed with the 100% CPU issue. plex-GoodLogs.zip is with libcppnetlib-uri.so rpelaced with one I built myself.

Hopefully you’ll be able to consider it a real issue now.plex-BadLogs.zip (19.5 KB) plex-GoodLogs.zip (19.4 KB)

EDIT: Can’t update .tgz files. .zip files reacted and added.

1 Like

Hi @mikec_pt, this is a known issue and I’m somewhat surprised by your response, considering you’re a Plex Employee and that this has been discussed and investigated extensively on the forums. We’ve been told repeatedly by sa2000 and chuckpa that this is “with engineering” (hence I’d expect you to have visibility of it on the internal bug tracker) but that, sadly, they’re waiting for a change in the libcpp code rather than Plex fixing the problem in their implementation.

@Realdeuce - there’s lots more information here and here.

Basically, you need to disable UPnP (not NAT-PMP, just UPnP) on your router (which I’m assuming is running OpenWRT) then restart the PMS service, or roll back to PMS 1.14.0.5470.

Disabling UPnP means you’ll need to manually configure any port forwards for Plex remote access (and whatever other services you run internally and expose to the Internet) but it is likely to break some gaming stuff if you’re a Playstation or Xbox user as some games dynamically configure port forwards using UPnP.

Guess we’ve all been experiencing a fake issue

1 Like

@gary_parker My reply was to the this specific post which states there an infinite loop in libcppnetlib-uri on a freebsd server and also mentions version 1.15.3.

I don’t know if there’s is a specific issue there and the info provided is doesn’t help (as there are no debug symbols)

Hence why I said:

Regardless the best advice I can give is update, check if you still have 100% cpu usage and submit logs.

I am not saying “there is no issue here, move along” .

Also there were changes in Upnp related code since those other posts (one of those is for v 1.14 i.e that’s even before the new build system… so there’s that as well), if its not happening on the current public or beta then it is no longer an issue!

That said, @RealDeuce can you please update, and confirm this is the same issue described by other user, and those the proposed solution fixes it for you (assuming you are also using OpenWRT ofc)

If you’re not using OpenWRT I would still perhaps try the same thing, or even try with manual mapping and see if the issue goes away.

If it has nothing to do it with then logs are still always helpful ofc, feel free to DM them if you don’t want to post here.

I don’t know… the original post doesn’t exactly provide much info on what the issue is, expect for the fact that replacing a lib seems to fix it.

Are you saying that you also see 100% usage (on freebsd) and replacing such lib fixes it for you?

Can you then provide more details on it, is it also related to Remote Access!?

Thanks for taking the time to reply, Mike. This issue has definitely been observed on freebsd previously (as well as macos, Linux and windows based systems) in other thread (there are many on this subject). I’d have hoped this was reflected in the notes on your internal bug tracker, but it’s obvious that not all the hard work put in by the community members is collated or used.

If the data isn’t in the bug tracker I’m afraid you’re going to have put in the legwork to find all the threads on the forum around this issue yourself, or take our word for it.

As a starter, though, using previous versions of the libcpp uri library was not a fix. To be clear, the workaround is to regress to a version of PMS that does not use libcpp uri functionality at all.

Apologies I did not make my self clear, I’m not saying that the UpnP issues are untracked, in fact as I stated there’s been some changes in that area in recent builds that actually fixed a lot of problems, but sadly its seems that its not yet the case for this one (assuming its the same as the other post).

To be fair some of this platforms (perhaps its the cases with OpenWRT, depending on the version) also use ancient upnp libs/implementations and in same cases this might mean we can no longer make it work well there… (and I’m not stating its the case here but I can say it was indeed the case in the past for some other issues, and I do recall one where we were actually able to patch it in a way that would work for all).

I must clarify that my first response was intended as: “I’m not exactly sure what you are reporting here, can you update, try again and send more details” (the library i.e. was bumped in newer releases)

I didn’t even consider this related to the others, because I mostly tend to the FreeBSD specific cases, as there a lot more “100% CPU usage” topics so its harder to make the relation, now if I had search for libcppnetlib the story would be different, but again since quite a few things changes I still wanted the Original Poster to upgrade first!

Again I apologize if my 1st response that gave the wrong idea.

Now moving along to the issue it self I can’t replicate it because as you state the user is probably also using OpenWRT… I wonder which device though and firmware version…

As a starter, though, using previous versions of the libcpp uri library was not a fix. To be clear, the workaround is to regress to a version of PMS that does not use libcpp uri functionality at all.

Ah interesting, @RealDeuce seems to suggest replacing the lib fixed it for him.

@RealDeuce can you confirm that? or perhaps I misunderstood, and also are you using OpenWRT?

1 Like

Thanks Mike, that makes sense, and sorry for the terseness/tone of my previous replies. As you’ve likely figured out, this is a long running issue that a number of users have gotten pretty fed up with. You’ve stumbled into it and you don’t deserve our ire, sorry :pleading_face:

When I said that replacing the library didn’t fix it, I misspoke. Following some digging, with chuckpa’s help, we couldn’t narrow it down to a specific version of cpp-netlib causing the problem (as the library wasn’t even present on some platforms), but more that the behaviour manifested only when PMS first started using cpp-netlib’s uri parsing functionality in version 1.14.1.5488, and that it’s remained ever since on all platforms it was previously seen on.

Here’s the first mention we found specifically tying it to cpp-netlib on a Windows machine:

The correlation isn’t unique to users with routers running OpenWrt, although this is by far the majority (users with Amplifi, Bitdefender and Gargoyle based systems, also running miniupnpd, have all reported the issue). The correlation is with the minupnpd software (http://miniupnp.free.fr / [OpenWrt Wiki] packages:pkgdata:miniupnpd) that OpenWrt uses for UPnP functionality. I say this as we had one user who was operating a hand-rolled router with the miniupnpd software on it and observing the same issue.

miniupnpd has had some minor updates recently but is broadly up to date (2.1.20190408-2, one release behind current) on OpenWrt 18.06.02 (current stable release) and has received updates since PMS first began exhibiting this behaviour (December 2018).

I suggested that the Plex developers reach out to the miniupnd developer and/or cpp-netlib team to investigate further or even simply register an issue on GitHub, rather than waiting for a new release and hoping for the best, but nothing appears to have been done about this.

I note that @realdeuce mentions building a 0.13.0 release of cpp-netlib and using that on his freebsd machine seems to fix the issue for him. 0.13.0 has been out since July last year, so I wonder what version Plex are using for their statically compiled binary releases? :thinking: (the cpp-netlib libraries are not found on all platforms suffering the issue, so I’m guessing that Plex statically compile the libs in to these platforms?).

FYI, this has nothing to do with PMS announcing its services via UPnP, or finding other media devices. You can completely disable UPnP within PMS and it still occurs. It seems to be PMS querying the IGD that’s announced by miniupnpd for the network and running some tests to ensure that remote access will operate correctly (specifically, I think it’s checking for double-NAT). PMS started using cpp-netlib’s URI component to do this in version 1.14.1.5488. It doesn’t seem to like the output it receives from some instances of miniupnpd and gets into a loop.

Thanks for the details, and no worries, I understand where you are coming from and thanks for jumping in and clarifying the source of the issue, this is helpful :slight_smile:

I can also confirm this is indeed raised internally and being looked at, it seems it might not need just the lib bump but a fix on our side too (I can’t say for certainty, but I will try to clear that out).

1 Like

Basically, you need to disable UPnP (not NAT-PMP, just UPnP) on your router (which I’m assuming is running OpenWRT) then restart the PMS service, or roll back to PMS 1.14.0.5470.

This actually is running on my “router”, the box has direct access to the internet. Disabling UPnP was the first thing I tried based on an old Linux thread… I just changed the port Plex used for UPnP to 1901. It’s pretty straightforward to hexedit libminiupnpc.so.10 and Plex Media Server to use port 1901. This looked promising at first but ultimately failed.

Keeping Plex from binding port 1900 is important since my UPnP server needs it.

Disabling UPnP means you’ll need to manually configure any port forwards for Plex remote access (and whatever other services you run internally and expose to the Internet)

Since the box I run it on is directly on the internet, I don’t actually need Plex to do any UPnP magic to access the internet.

If you’re not using OpenWRT I would still perhaps try the same thing, or even try with manual mapping and see if the issue goes away.

Plex is running on an internet IP in my case. It doesn’t need the IGD at all.

Ah, now you’re going to run into the problem of not running it the way Plex thinks everyone should be running it :rofl:

  • your server has public IP address so you’d think you don’t need to use Plex’s remote access functions. If you turn off remote access, though, it won’t be accessible, even without firewall holes in place, due to all the registering the server does with Plex.tv
  • even if you disable remote access your PMS instance will still multicast every now and again to find any IGDs on the network

I seem to recall someone working around the issue by blocking the incoming SSDP packets from the router to the server PMS was hosted on, but this will be challenging as it’s all on the same box for you :thinking:

Can you confirm, btw, that you’re running miniupnpd on your router?

Are you saying that you also see 100% usage (on freebsd) and replacing such lib fixes it for you?

Yes.

Can you then provide more details on it, is it also related to Remote Access!?

I did not try disabling remote access. I can try that later today. I’ll also grab a capture on port 1900 to see what Plex is still doing with UPnP. I suspect the constant “NetworkServiceBrowser: Error sending out discover packet from 107.5.177.180 to 107.5.179.255: Host is down” entries in my log is Plex trying to use UPnP with my ISP to punch a hole in the nonexistant firewall.

As far as what I did, my system is pretty much fully updated with current HEAD ports, so the following versions of the dependencies:

asio-1.10.6_7
boost-libs-1.70.0_2
ca_root_nss-3.44
cmake-3.14.5
curl-7.65.1
expat-2.2.6_1
gettext-runtime-0.19.8.1_2
icu-64.2,1
indexinfo-0.3.1
jsoncpp-1.8.1_6
libarchive-3.3.3,1
libffi-3.2.1_3
liblz4-1.9.1,1
libnghttp2-1.38.0
libuv-1.29.1
lzo2-2.10_1
ninja-1.9.0,2
python36-3.6.8_2
readline-8.0.0
rhash-1.3.5

I then went into /usr/ports/devel/cpp-netlib, bumped DISTVERSION to 0.13.0, did a make makesum the a make.

Finally, I coped libcppnetlib-uri.so from the staging directory into my plex lib directory and restarted Plex.

Ah interesting, @RealDeuce seems to suggest replacing the lib fixed it for him.

@RealDeuce can you confirm that? or perhaps I misunderstood, and also are you using OpenWRT?

My Plex box is directly on the internet. It does run minissdpd and miniupnpd, but if Plex is trying to get an IGD to open a port, it will be asking my ISP, not itself.

I replaced the library with one I build myself, not one distributed by Plex, and it did solve the issue.

1 Like

Can you confirm, btw, that you’re running miniupnpd on your router?

Yes, miniupnpd is running alongside Plex on that box, and has port 1900 bound. Plex will not be able to bind port 1900 (which it tries to do when DLNA is enabled). hexediting it to bind 1901 allows me to leave DLNA enabled, but I doubt that’ll actually work.

Ideally, Plex would use the minissdpd UNIX-domain socket so it could actually do UPnP stuff, but that’s a bit of an esoteric feature.

1 Like

Here’s the link to the post where blocking port 1900 was mentioned:

It’s not trying to open a port, it’s querying the IGD for it’s IP address to check if it’s double-NAT’d. I believe that, even with Remote Access turned off, PMS still queries any IGDs it finds on the LAN and parses their replies (badly).

Also, lots of detail on past packet dumps of PMS’s SSDP and GDM activity here:

It’d be interesting to see if you’re seeing similar behaviour on your network.

I’ve now confirmed that Plex doesn’t manage to get any UPnP responses, and it only appears to solicit them from my ISP. This makes sense since binding to port 1900 on the local network will fail and it doesn’t appear to try using the minissdpd socket.

It’d be interesting to see if you’re seeing similar behaviour on your network.

It appears I see around four discovery packets when Plex starts up, but I don’t see busts after that.

With the old lib, even if I disable remote access, Plex still uses 100% CPU and attempts to send discover packets to my ISP.