Skip to content

Fix exec command#259

Open
diggit wants to merge 2 commits intosquare:masterfrom
diggit:fix_exec_command
Open

Fix exec command#259
diggit wants to merge 2 commits intosquare:masterfrom
diggit:fix_exec_command

Conversation

@diggit
Copy link
Copy Markdown
Contributor

@diggit diggit commented Feb 21, 2026

If exec_command is called before open, DLL opens connection to some probe it picks, which then causes issues when open is called afterwards.

resolves #254

If called before open, DLL opens connection to _some_ probe it picks
which then causes issues when `open` is called afterwards.

resolves square#254
I hope the one line change counts too.
Copy link
Copy Markdown
Contributor

@hkpeprah hkpeprah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is universally true. I believe it depends on the command being used. For example, I have no debugger attached and am able to do this:

import pylink
>>> jl = pylink.JLink()
>>> jl.disable_dialog_boxes()

@diggit
Copy link
Copy Markdown
Contributor Author

diggit commented Feb 22, 2026

If I revert back, detached J-Link and do...

import pylink
import time

jl = pylink.JLink()
jl.disable_dialog_boxes()
time.sleep(1)

...and nothing else. I get "probe selection" popup window. J-Link SW 9.20.
I hit esc multiple times and then I see

API Error: API JLINK_ExecCommand function called before JLINKARM_Open()
API Error: API JLINK_ExecCommand function called before JLINKARM_Open()
fish: Job 1, './experiments.py' terminated by signal SIGSEGV (Address boundary error)

in the stdout.

Then I tried each exec_command from disable_dialog_boxes individually.
Do not cause error and following open works normally:

  • self.exec_command('SilentUpdateFW')
  • self.exec_command('SuppressInfoUpdateFW')
  • self.exec_command('SetBatchMode = 1')
  • self.exec_command("SuppressControlPanel")

Cause error (need probe opened, auto calls open when the probe is attached):

  • self.exec_command("HideDeviceSelection = 1")
  • self.exec_command("DisableInfoWinFlashDL")
  • self.exec_command("DisableInfoWinFlashBPs")

@hkpeprah
Copy link
Copy Markdown
Contributor

Could you provide some details about your setup? Is this on Windows, Linux or OSX? It could be possible that behaviour is changed in later versions of the SDK and/or that behaviour depends on some combination of command + platform + SDK version.

@diggit
Copy link
Copy Markdown
Contributor Author

diggit commented Feb 22, 2026

My setup is mostly described on #254.
In summary:
OS: Archlinux (up to date)
J-Link 9.14a, 9.16, 9.20
Probe: J-Link Base compact 12.0

I would suspect the change of behavior in some recent dll.

@dottspina
Copy link
Copy Markdown
Contributor

Faced with the same problem as #254 when working with pyOCD (nRF52840-DK), I too had started to look into it (in short, pyOCD also calls disable_dialog_boxes() before open(), see pyocd/pyOCD#1927 ).

@diggit, my findings seem to confirm yours (my OS is also Linux):

  • I can reproduce the error with all versions above v9.12 of JLink DLL, tested with anything available from 9.14a to 9.24.
  • the commands in disable_dialog_boxes() that trigger automatic connections are "HideDeviceSelection = 1" , "DisableInfoWinFlashDL" and ""DisableInfoWinFlashBPs"
  • adding the @open_required decorator to JLink.exec_command() fixes the issue

Although opening the emulator may not be required for all commands, I support this merge request (AFAICT).
I even think it should be backported to the 1.7 branch: pyOCD requires pylink-square>=1.0,<2.0 and is affected by this issue.

A question: is calling disable_dialog_boxes() before open() considered a bad practice anyway ?

Thanks.

@hkpeprah
Copy link
Copy Markdown
Contributor

@dottspina Thanks for the additional metric. @diggit , I've been thinking about how to approach this without making open_required required before disabling any of the dialog boxes. I wonder if we can workaround this with a state variable and some tracking in the .open() method? From a high level:

  • Set a _disable_dialog_boxes: bool = False state variable in open().
  • In disable_dialog_boxes(), check if the SDK version is >= the known breaking version and skip the specific calls @dottspina called out if the debugger connection has not been opened yet, but set _disable_dialog_boxes to True
  • In open(), call disable_dialog_boxes() after opening the debugger connection if _disable_dialog_boxes is True, then set it to False.
  • In enable_dialog_boxes(), clear the _disable_dialog_boxes (set to False).

What do you think? I think this would make the behaviour transparent to those who upgrade to newer SDK versions while preserving existing behaviour for those on older SDKs.

@diggit
Copy link
Copy Markdown
Contributor Author

diggit commented Mar 13, 2026

That sounds good!
How would you handle this scenario?

  • disable_dialog_boxes()
  • enable_dialog_boxes()
  • disable_dialog_boxes()
  • enable_dialog_boxes()
  • open()

a) defer whole sequence (easiest to implement)
b) deduplicate calls of same functions and defer

  • open()
  • disable_dialog_boxes()
  • enable_dialog_boxes()

c) deduplicate calls of same functions and collapse complementary calls and defer

  • open()
  • enable_dialog_boxes()

d) ?

@hkpeprah
Copy link
Copy Markdown
Contributor

I wouldn't worry about de-duplicating the calls made. On Windows, some dialog boxes will open when you do open(), so we want those boxes to still be hidden, so I would just gate the specific ones that fail in the new SDK on the version check if not opened:

def disable_dialog_boxes():
    <disable dialogs that do not fail in new SDK w/o open>

    if <sdk_version < breaking_version> or <jlink opened>:
        <disable remaining dialog boxes>

dottspina added a commit to dottspina/pyOCD that referenced this pull request Mar 23, 2026
With JLink DLL versions 9.14 and above, calling disable_dialog_boxes()
before open() puts the pylink adapter into an inconsistent state.
As a result pyOCD will fail to open the J-Link emulator,
and possibly segfault.

The approach here is to preserve the current behavior as much
as possible, while allowing to develop/test/use pyOCD with
current versions of the JLink DLL.

See:
- pyocd#1925 "Jlink V9.22 No emulator with serial number"
- pyocd#1927 "probe: jlink: open emulator before issuing commands"
- square/pylink#259 "Fix exec command"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't connect to the emulator

3 participants