bark
@bark

that is, i wanted to

install matlab

you may already see why this is-

MATLAB R2023a (Not Responding)

... a bad idea.

but MathWorks have a Docker Container, which seemed like a good way to not have it destroy my system. and it was!!! downloading stuff took ages. whatever. expected that, plus it's cached so i'm not angry yet. one problem.

the6p4c@dragonfruit
20:00 🥺 ~> docker run -it --rm -e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:ro --shm-size=512M \
mathworks/matlab:r2023a

Running matlab

Starting MATLAB with license: [blah blah] - MATLAB (Individual)
[dear reader: pause here for about
10 minutes to simulate the issue]

so that's annoying. why's it so slow to launch?? i tried not using --rm to see if it was a first-boot thing, but it happened every time, no matter what i did or didn't do.

‼️ we have a puzzle 🧩 to solve ✨


uhhh what if it's doing a lot of io or network or something silly. let's strace it, i guess?

the6p4c@dragonfruit
20:15 🐾 ~> docker run --rm -it \
--entrypoint /bin/bash mathworks/matlab:r2023a
matlab@2dcc8a36dbc3:~/Documents/MATLAB$ strace -f matlab
bash: strace: command not found
🐶❓ ok um
matlab@2dcc8a36dbc3:~/Documents/MATLAB$ sudo apt-get update \
&& sudo apt-get install strace
[oh so much output]
matlab@2dcc8a36dbc3:~/Documents/MATLAB$ strace -f matlab
...
[pid 822] close(871631) = -1 EBADF (Bad file descriptor)
[pid 822] close(871632) = -1 EBADF (Bad file descriptor)
[pid 822] close(871633) = -1 EBADF (Bad file descriptor)
...

right. well i would call this abnormal. it seems like it's trying to close every single file descriptor, one by one. why. we can kinda find out where this is all happening with strace -k, which'll give us a stack trace for each syscall.

here's the stacktrace. comes with a ⚠️ long ⚠️ warning
[pid 927] close(643) = -1 EBADF (Bad file descriptor)
 > /usr/lib/x86_64-linux-gnu/libpthread-2.31.so(__close+0x3b) [0x1345b]
 > /opt/matlab/R2023a/bin/glnxa64/libmwfl.so(mwboost::thread::thread<mwboost::_bi::bind_t<mwboost::variant<foundation::core::process::detail::unknown, foundation::core::process::detail::exited, foundation::core::process::detail::signaled>, mwboost::variant<foundation::core::process::detail::unknown, foundation::core::process::detail::exited, foundation::core::process::detail::signaled> (*)(mwboost::shared_ptr<foundation::core::sysdep::posix::process_impl<foundation::core::sysdep::linux::process_impl> > const&, bool), mwboost::_bi::list2<mwboost::_bi::value<mwboost::shared_ptr<foundation::core::sysdep::linux::process_impl> >, mwboost::_bi::value<bool> > > >(mwboost::_bi::bind_t<mwboost::variant<foundation::core::process::detail::unknown, foundation::core::process::detail::exited, foundation::core::process::detail::signaled>, mwboost::variant<foundation::core::process::detail::unknown, foundation::core::process::detail::exited, foundation::core::process::detail::signaled> (*)(mwboost::shared_ptr<foundation::core::sysdep::posix::process_impl<foundation::core::sysdep::linux::process_impl> > const&, bool), mwboost::_bi::list2<mwboost::_bi::value<mwboost::shared_ptr<foundation::core::sysdep::linux::process_impl> >, mwboost::_bi::value<bool> > >&&)+0x26ed) [0x9581d]
 > /opt/matlab/R2023a/bin/glnxa64/libmwfl.so(foundation::core::process::process::process(foundation::core::process::command const&, foundation::core::process::context const&)+0x15) [0x8f905]
 > /opt/matlab/R2023a/bin/glnxa64/matlabLNU(mwboost::wrapexcept<mwboost::uuids::entropy_error>::rethrow() const+0x255a) [0x10e44]
 > /usr/lib/x86_64-linux-gnu/libc-2.31.so(__libc_start_main+0xf3) [0x24083]
 > /opt/matlab/R2023a/bin/glnxa64/matlabLNU(mwboost::wrapexcept<mwboost::uuids::entropy_error>::rethrow() const+0x2ba0) [0x1148a]

you didn't read a lick of that did you

anyway

ok so it's happening somewhere deep inside libmwfl.so. let's yoink it and go looking. i will spare you the horrors of decompiled code by renaming variables and such

fd = 3;
if (2 < dtablesize) {
  do {
    ...
    if (local_1d8 == (undefined4 *)0x0) {
      ...
      ret = close(fd);
      if (ret == -1) {
        errno = __errno_location();
        if (*errno != EBADF) goto error_close_open_fds;
      }
    }
    else {
      ...
    }
    fd += 1;
    if (dtablesize < fd) break;
  } while( true );
}

sure looks intentional!!!! loop through every single possible fd and close them, one by one. it appears this is part of a fork or exec implementation (?) judging by some of the strings: close_post_fork and such.

it seems like a pretty normal thing to do tbh? i wonder why it might be causing a problem

the6p4c@dragonfruit
21:00 💜 ~> grep -E "Limit|Max open files" \
/proc/`pidof dockerd`/limits
Limit                     Soft Limit           Hard Limit           Units
Max open files            1073741816           1073741816           files
oh

yeah ok let's fix that real quick

the6p4c@dragonfruit
21:01 😍 ~> docker run --rm -it -e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
--ulimit nofile=65536 --shm-size=512M \
mathworks/matlab:r2023a

Running matlab

Starting MATLAB with license: [blah blah] - MATLAB (Individual)
[dear reader: open MATLAB on your own
machine to simulate it working]
⭐ done! you can even see it, completely unfit for purpose, right here

You must log in to comment.

in reply to @bark's post:

I'm also not sure why it seems to be catching an error thrown after generating a UUID fails due to a lack of entropy (maybe? wonder if it's trying to read /dev/random and that's not mapped into the Docker container) and ... launching a new process while handling that? It is a mystery.

ah, so, since it’s a mostly stripped binary, the symbols in the stack trace are just the only things with names before the actual address - hence the really big offsets at the end since the actual code is nowhere near those few functions with symbols. that tripped me up at first too

okay genuine question bc i am definitely missing something here:
why is it closing file descriptors? especially file descriptors it isn’t using? what does this accomplish??? why not simply not do that????