Skip to content

Commit 43ea0e9

Browse files
committed
Introduces an optional dependency on the fluxbox window manager to support Simulink Online in Linux environments from MATLAB R2024b onwards.
fixes mathworks/jupyter-matlab-proxy#95 fixes #51
1 parent 4107044 commit 43ea0e9

File tree

7 files changed

+92
-27
lines changed

7 files changed

+92
-27
lines changed

Advanced-Usage.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The following table describes all the environment variables that you can set to
3232
| **MWI_CUSTOM_MATLAB_ROOT** | string (optional) | `"/path/to/matlab/root/"` | Optionally, provide a custom path to MATLAB root. For more information see [Adding MATLAB to System Path](#adding-matlab-to-system-path) |
3333
| **MWI_PROCESS_START_TIMEOUT** | integer (optional) | `1234` | This field controls the time (in seconds) for which `matlab-proxy` waits for the processes it spins up, viz: MATLAB & Xvfb, to respond. By default, this value is `600 seconds`. A timeout could either indicate an issue with the spawned processes or be a symptom of a resource-constrained environment. Increase this value if your environment needs more time for the spawned processes to start.|
3434
| **MWI_MATLAB_STARTUP_SCRIPT** | string (optional) | `"addpath('/path/to/a/folder'), c=12"` | Executes string provided at MATLAB startup. For details, see [Run Custom MATLAB Startup Code](#run-custom-matlab-startup-code) |
35-
| **MWI_SHUTDOWN_ON_IDLE_TIMEOUT** | integer (optional) | 60 | Defines the duration in minutes, that `matlab-proxy` remains idle before shutting down. When you do not set the variable, `matlab-proxy` will not shutdown when idle. For details, [see Shutdown on Idle](#shutdown-on-idle).
35+
| **MWI_SHUTDOWN_ON_IDLE_TIMEOUT** | integer (optional) | 60 | Defines the duration in minutes, that `matlab-proxy` remains idle before shutting down. When you do not set the variable, `matlab-proxy` will not shut down when idle. For details, [see Shutdown on Idle](#shutdown-on-idle). |
3636

3737
## Shutdown on Idle
3838

@@ -181,6 +181,6 @@ Note: Restarting MATLAB from within `matlab-proxy` will run the specified code a
181181

182182
----
183183

184-
Copyright 2020-2024 The MathWorks, Inc.
184+
Copyright 2020-2025 The MathWorks, Inc.
185185

186186
----

README.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
----
55

6-
`matlab-proxy` is a Python® package which enables you to launch MATLAB® and access it from a web browser.
6+
Use this Python® package `matlab-proxy` to start MATLAB® and access it from a web browser.
77

8-
Installation of this package creates an executable `matlab-proxy-app`, which launches MATLAB and provides a URL to access it.
8+
Install this package to create an executable `matlab-proxy-app`, which starts MATLAB and provides you a URL to access it.
99

10-
The MATLAB Proxy is under active development. For support or to report issues, see the [Feedback](#feedback) section.
10+
MATLAB Proxy is under active development. For support or to report issues, see [Feedback](#feedback).
1111

1212
----
1313

@@ -23,17 +23,19 @@ The MATLAB Proxy is under active development. For support or to report issues, s
2323
- [Feedback](#feedback)
2424

2525
## Requirements
26-
* MATLAB® R2020b or later is installed and on the system PATH.
26+
* MATLAB® R2020b or later, installed and added to the system PATH.
2727
```bash
2828
# Confirm MATLAB is on the PATH
2929
which matlab
3030
```
3131
* The dependencies required to run MATLAB.
32-
Refer to the Dockerfiles in the [matlab-deps](https://github.com/mathworks-ref-arch/container-images/tree/master/matlab-deps) repository for the desired version of MATLAB.
32+
For details, refer to the Dockerfiles in the [matlab-deps](https://github.com/mathworks-ref-arch/container-images/tree/master/matlab-deps) repository for your desired version of MATLAB.
3333

34-
* X Virtual Frame Buffer (Xvfb) : (only for Linux® based systems)
34+
* X Virtual Frame Buffer (Xvfb) (only for Linux® based systems):
35+
36+
Installing Xvfb is optional (starting v0.11.0 of matlab-proxy) but highly recommended. Xvfb enables graphical abilities like plots and figures in the MATLAB desktop.
37+
To install Xvfb on your Linux machine, use:
3538

36-
Install it on your linux machine using:
3739
```bash
3840
# On a Debian/Ubuntu based system:
3941
$ sudo apt install xvfb
@@ -46,7 +48,17 @@ The MATLAB Proxy is under active development. For support or to report issues, s
4648
$ sudo yum install xorg-x11-server-Xvfb
4749
```
4850

49-
*Note: The installation of Xvfb is **optional** (w.e.f. v0.11.0 of matlab-proxy). However, we highly recommend installing it.*
51+
52+
* Fluxbox Window Manager (only for Linux® based systems):
53+
54+
Installing fluxbox is optional but required to use Simulink Online.
55+
56+
Install fluxbox using:
57+
```bash
58+
# On a Debian/Ubuntu based system:
59+
$ sudo apt install fluxbox
60+
```
61+
5062
* Python versions: **3.8** | **3.9** | **3.10** | **3.11**
5163
* [Browser Requirements](https://www.mathworks.com/support/requirements/browser-requirements.html)
5264
* Supported Operating Systems:
@@ -84,7 +96,7 @@ which matlab-proxy-app
8496

8597
Once the `matlab-proxy` package is installed.
8698

87-
* Open a Linux terminal and launch the application with
99+
* Open a terminal and start `matlab-proxy-app`. On Linux, the command would be
88100
```bash
89101
env MWI_BASE_URL="/matlab" matlab-proxy-app
90102
```
@@ -131,7 +143,7 @@ The following options are available in the status panel (some options are only a
131143

132144
## Examples
133145
* For installing/usage in a Docker container, see this [Dockerfile](./examples/Dockerfile) and its [README](./examples/README.md).
134-
* For upgrading **matlab-proxy** in an existing Docker image, see this [Dockerfile.upgrade.matlab-proxy](./examples/Dockerfile.upgrade.matlab-proxy) and its [README](./examples/README.md#upgrading-matlab-proxy-package-in-a-docker-image).*
146+
* For upgrading **matlab-proxy** in an existing Docker image, see this [Dockerfile.upgrade.matlab-proxy](./examples/Dockerfile.upgrade.matlab-proxy) and its [README](./examples/README.md#upgrading-matlab-proxy-package-in-a-docker-image).
135147
* For usage in a Jupyter environment, see [jupyter-matlab-proxy](https://github.com/mathworks/jupyter-matlab-proxy).
136148

137149
## Platform Support
@@ -169,8 +181,10 @@ To install `matlab-proxy` in WSL 2, follow the steps mentioned in the [Installat
169181
`matlab-proxy` version `v0.7.0` introduces support for using an existing MATLAB license. Use the Existing License option only if you have an activated MATLAB. This allows you to start MATLAB without authenticating every time.
170182

171183
## Limitations
172-
This package supports the same subset of MATLAB features and commands as MATLAB® Online, except there is no support for Simulink® Online.
173-
[Click here for a full list of Specifications and Limitations for MATLAB Online](https://www.mathworks.com/products/matlab-online/limitations.html).
184+
This package supports the same set of MATLAB features and commands as MATLAB® Online. For the full list, see
185+
[Specifications and Limitations for MATLAB Online](https://www.mathworks.com/products/matlab-online/limitations.html).
186+
187+
Simulink Online is supported exclusively on Linux platforms starting from MATLAB R2024b.
174188

175189
## Security
176190
We take your security concerns seriously, and will attempt to address all concerns.

matlab_proxy/app_state.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
OnlineLicensingError,
3535
UIVisibleFatalError,
3636
XvfbError,
37+
WindowManagerError,
3738
log_error,
3839
)
3940

@@ -548,7 +549,7 @@ def _are_required_processes_ready(
548549

549550
if system.is_linux():
550551
# If Xvfb is on system PATH, check if it up and running.
551-
if self.settings["is_xvfb_available"] and (
552+
if self.settings.get("is_xvfb_available", None) and (
552553
xvfb_process is None or xvfb_process.returncode is not None
553554
):
554555
logger.debug(
@@ -1000,11 +1001,6 @@ async def __setup_env_for_matlab(self) -> dict:
10001001
f"MW_CONNECTOR_CONTEXT_ROOT is set to: {matlab_env['MW_CONNECTOR_CONTEXT_ROOT']}"
10011002
)
10021003

1003-
# Setup Simulink Online which requires a pre-warm stage
1004-
if mwi_env.Experimental.is_simulink_enabled():
1005-
logger.info("Enabling usage of Simulink Online...")
1006-
matlab_env["PREWARM_SIMULINK"] = "true"
1007-
10081004
# Env setup related to logging
10091005
# Very verbose logging in debug mode
10101006
if logger.isEnabledFor(logging.getLevelName("DEBUG")):
@@ -1052,6 +1048,31 @@ def __filter_env_variables(env_vars: dict, prefix: str) -> dict:
10521048
key: value for key, value in env_vars.items() if not key.startswith(prefix)
10531049
}
10541050

1051+
async def __start_window_manager(self, display=None):
1052+
if display is None:
1053+
logger.info("Not starting fluxbox as display is not provided")
1054+
return None
1055+
1056+
wm_env = os.environ.copy()
1057+
wm_env["DISPLAY"] = display
1058+
wm_cmd = ["fluxbox", "-screen", "0", "-log", "/dev/null"]
1059+
1060+
try:
1061+
logger.info(f"Starting window manager with DISPLAY={wm_env['DISPLAY']}")
1062+
return await asyncio.create_subprocess_exec(
1063+
*wm_cmd, close_fds=False, env=wm_env, stderr=asyncio.subprocess.PIPE
1064+
)
1065+
1066+
except Exception as err:
1067+
self.error = WindowManagerError(
1068+
"Unable to start the Fluxbox Window Manager due to the following error: "
1069+
+ err
1070+
)
1071+
# Log the error on the console.
1072+
log_error(logger, self.error)
1073+
1074+
return None
1075+
10551076
async def __start_xvfb_process(self):
10561077
"""Private method to start the xvfb process. Will set appropriate
10571078
errors to self.error and return None when any exceptions are raised.
@@ -1073,7 +1094,7 @@ async def __start_xvfb_process(self):
10731094
)
10741095
self.settings["matlab_display"] = ":" + str(display_port)
10751096

1076-
logger.debug(f"Started Xvfb with PID={xvfb.pid} on DISPLAY={display_port}")
1097+
logger.info(f"Started Xvfb with PID={xvfb.pid} on DISPLAY={display_port}")
10771098

10781099
return xvfb
10791100

@@ -1303,7 +1324,13 @@ async def start_matlab(self, restart_matlab=False):
13031324

13041325
self.processes["xvfb"] = xvfb
13051326

1327+
# Start Window Manager on linux if possible
1328+
if system.is_linux() and self.settings["is_windowmanager_available"]:
1329+
display = self.settings.get("matlab_display", None)
1330+
await self.__start_window_manager(display)
1331+
13061332
try:
1333+
13071334
# Prepare ready file for the MATLAB process.
13081335
self.create_logs_dir_for_MATLAB()
13091336

matlab_proxy/settings.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ def get_dev_settings(config):
218218
),
219219
"warnings": [],
220220
"is_xvfb_available": False,
221+
"is_windowmanager_available": False,
221222
"mwi_idle_timeout": None,
222223
}
223224

@@ -271,12 +272,21 @@ def get(config_name=matlab_proxy.get_default_config_name(), dev=False):
271272
settings.update(get_server_settings(config_name))
272273

273274
settings["is_xvfb_available"] = True if shutil.which("Xvfb") else False
275+
settings["is_windowmanager_available"] = (
276+
True if shutil.which("fluxbox") else False
277+
)
274278

275279
# Warn user if xvfb is not available on system path.
276-
if system.is_linux() and not settings["is_xvfb_available"]:
277-
warning = " Unable to find Xvfb on the system PATH. Xvfb enables graphical abilities like plots and figures in the MATLAB desktop.\nConsider adding Xvfb to the system PATH and restart matlab-proxy. See https://github.com/mathworks/matlab-proxy#requirements for information."
278-
logger.warning(warning)
279-
settings["warnings"].append(warning)
280+
if system.is_linux():
281+
if not settings["is_xvfb_available"]:
282+
warning = " Unable to find Xvfb on the system PATH. Xvfb enables graphical abilities like plots and figures in the MATLAB desktop.\nConsider adding Xvfb to the system PATH and restart matlab-proxy.\nFor details, see https://github.com/mathworks/matlab-proxy#requirements."
283+
logger.warning(warning)
284+
settings["warnings"].append(warning)
285+
286+
if not settings["is_windowmanager_available"]:
287+
warning = " Unable to find fluxbox on the system PATH. To use Simulink Online, add Fluxbox to the system PATH and restart matlab-proxy. For details, see https://github.com/mathworks/matlab-proxy#requirements."
288+
logger.warning(warning)
289+
settings["warnings"].append(warning)
280290

281291
settings.update(get_matlab_settings())
282292

matlab_proxy/util/mwi/environment_variables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,5 +196,5 @@ def get_env_name_profile_matlab_startup():
196196

197197
@staticmethod
198198
def is_matlab_startup_profiling_enabled():
199-
"""Returns true if the simulink online is enabled."""
199+
"""Returns true if the startup profiling is enabled."""
200200
return _is_env_set_to_true(Experimental.get_env_name_profile_matlab_startup())

matlab_proxy/util/mwi/exceptions.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2020-2024 The MathWorks, Inc.
1+
# Copyright 2020-2025 The MathWorks, Inc.
22

33

44
class AppError(Exception):
@@ -139,6 +139,19 @@ class XvfbError(AppError):
139139
pass
140140

141141

142+
class WindowManagerError(AppError):
143+
"""A Class which inherits the AppError class.
144+
145+
This class represents any errors raised when instantiating a Window Manager within the Xvfb DISPLAY.
146+
147+
Args:
148+
AppError (Class): Parent Class containing attributes to store
149+
messages, logs and stacktrace.
150+
"""
151+
152+
pass
153+
154+
142155
class EmbeddedConnectorError(MatlabError):
143156
"""A Class which inherits the MatlabError class.
144157

tests/unit/test_app_state.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def sample_settings_fixture(tmp_path):
4343
"warnings": [],
4444
"matlab_config_file": tmp_file,
4545
"is_xvfb_available": True,
46+
"is_windowmanager_available": True,
4647
"mwi_server_url": "dummy",
4748
"mwi_logs_root_dir": Path(settings.get_mwi_config_folder(dev=True)),
4849
"app_port": 12345,

0 commit comments

Comments
 (0)