MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.

    MMM-Remote-Control

    Scheduled Pinned Locked Moved Utilities
    57 Posts 9 Posters 2.5k Views 8 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R Offline
      rkorell @KristjanESPERANTO
      last edited by

      @KristjanESPERANTO Dear Kristijan,

      after a long time I finally managed to see your “new” modul.
      First of all: Thanks a lot for your effort, again - nice piece!

      In the past few days I’ve completely rebuilt my mirror and migrated it to trixie as well as to the actual mirror and node versions.

      I ran into a reproducible issue with the restart functionality when MagicMirror is managed by pm2 (which is the recommended setup per the official MagicMirror documentation).

      The Problem

      When triggering a restart via the Remote-Control UI (or the /api/restart endpoint), MagicMirror enters an endless crash-loop with EADDRINUSE: address already in use :::8080.

      Root Cause
      The handleRestart function in node_helper.js (lines 717-741) uses the Electron-native restart mechanism:

      const {app} = require("electron");
      app.relaunch();
      app.quit();
      

      This works fine in standalone mode, but creates a race condition with pm2:

      1. app.relaunch() spawns a new Electron instance (child of the current process)
      2. app.quit() terminates the current Electron instance
      3. pm2 detects the termination as a crash and spawns another Electron instance
      4. Now two Electron instances compete for port 8080 → EADDRINUSE → both crash → pm2 keeps restarting → infinite loop

      The only way to recover is to manually identify and kill the orphaned Electron process, then trigger a clean restart via touch config.js (which pm2’s file-watch picks up).

      Interestingly, the catch-block fallback for server mode (lines 726-739) already does it correctly — it calls process.exit(0) and lets the process manager handle the restart. The Electron code path just doesn’t account for the pm2 scenario.

      Possible Fix

      When running under pm2, the Electron-native app.relaunch() should be skipped entirely.

      pm2 can be detected via environment variables like PM2_HOME, pm_id, or PM2_USAGE:

      handleRestart (query, res) {
        try {
          const {app} = require("electron");
          if (!app) { throw "Could not get Electron app instance."; }
      
          // When running under pm2, don't use app.relaunch() — pm2 handles restart
          if (process.env.PM2_HOME || process.env.pm_id !== undefined) {
            Log.log("Running under pm2, exiting cleanly for process manager restart...");
            this.sendResponse(res, undefined, {action: "RESTART", info: "Exiting for pm2 restart..."});
            setTimeout(() => app.quit(), 1000);
            return;
          }
      
          this.sendResponse(res, undefined, {action: "RESTART", info: "Restarting Electron..."});
          app.relaunch();
          app.quit();
        } catch (error) {
          // ... existing server mode fallback ...
        }
      }
      

      Environment

      • MagicMirror 2.34.0
      • MMM-Remote-Control 4.2.2 (commit b854832)
      • Node.js v22, Electron 39.5.2
      • Raspberry Pi 5, Debian 13 (Trixie)
      • Process manager: pm2 with file-watch on config.js

      Workaround

      For now, I’ve documented this for my setup: never use the restart button in Remote-Control. Monitor ON/OFF works fine, only the restart is
      affected.

      Thanks for considering this — happy to test any fix if needed!

      Warmest regards,
      Ralf

      KristjanESPERANTOK 1 Reply Last reply Reply Quote 1
      • KristjanESPERANTOK Online
        KristjanESPERANTO Module Developer @vtek
        last edited by

        Hi @vtek, glad you figured it out! Just for reference: when secureEndpoints: true is set, the API key can be passed in two ways:

        1. URL parameter: ?apiKey=YOUR_KEY
        2. HTTP header: Authorization: apiKey YOUR_KEY

        Also, starting with v4.2.4 the error message now directly hints at the solution, so the next person running into this should find it faster 🙂

        1 Reply Last reply Reply Quote 0
        • KristjanESPERANTOK Online
          KristjanESPERANTO Module Developer @rkorell
          last edited by

          Hi @rkorell, thank you for the detailed bug report — the root cause analysis was spot on and made it straightforward to fix!

          The fix is included in v4.2.4: when MMM-Remote-Control detects it’s running under pm2 (via PM2_HOME or pm_id environment variables), it now skips app.relaunch() and only calls app.quit(), letting pm2 handle the restart cleanly.

          Would be great if you could confirm it works on your setup!

          R 1 Reply Last reply Reply Quote 0
          • R Offline
            rkorell @KristjanESPERANTO
            last edited by

            @KristjanESPERANTO Dear Kristijan,
            just tested v4.2.4 — works perfectly! Restart via the Remote-Control UI now completes cleanly
            under pm2, no orphaned Electron process, no port conflict. Exactly the behavior you’d expect.

            I also noticed you added a dedicated handleRestart.test.js with 210 lines of unit tests covering
            both the pm2 and standalone code paths — that’s really impressive and goes well beyond just a
            quick fix. Having proper test coverage for this kind of dual-mode behavior is exactly the right
            thing to do. Much appreciated!

            Thanks for the incredibly fast turnaround and the quality of the fix. Consider this confirmed
            working on:

            • MagicMirror 2.34.0
            • MMM-Remote-Control 4.2.4
            • Node.js v22, Electron 39.5.2
            • Raspberry Pi 5, Debian 13 (Trixie)
            • pm2 with file-watch

            Warmest regards,
            Ralf

            KristjanESPERANTOK 1 Reply Last reply Reply Quote 1
            • KristjanESPERANTOK Online
              KristjanESPERANTO Module Developer @rkorell
              last edited by

              @rkorell Thank you very much for this feedback and appreciation 🙂 It’s interesting that you took a deeper look at the changes.

              1 Reply Last reply Reply Quote 0
              • 1
              • 2
              • 3
              • 4
              • 5
              • 6
              • 6 / 6
              • First post
                Last post
              Enjoying MagicMirror? Please consider a donation!
              MagicMirror created by Michael Teeuw.
              Forum managed by Sam, technical setup by Karsten.
              This forum is using NodeBB as its core | Contributors
              Contact | Privacy Policy