nrfSniffer only works one time at Wireshark startup

I have the software installed and I am using the nRF52840DK with Ubuntu 22.04. The uart link is /dev/ttyACM0

When I start wireshark and do a capture on all advertising channels, it works fine. However, when I stop the capture and then try to restart a second capture, I get no Packets found.

If I stop wireshark and restart, again I can do one but only one capture; this is repeatable.

Before starting a second capture I have done a >lsof /dev/ttyACM0 in case it was still open and locked, but this command came back with nothing. I have also started to try some of the straight python examples from the doc ble-sniffer subdirectory, and so far these seem to work as expected. However, it would be nice to get wireshark usable. Any suggestions? 

  • VERSION_STRING = "4.1.1"

    and copied from nrf_sniffer_ble.sh (last line of bash script):

    exec $py3 $script_path/nrf_sniffer_ble.py "$@"

    All software was downloaded in the last 4 weeks from scratch.

    On a related note: copying example_linux.py from doc to .config/wireshark/extcap and running the first time gives:

    ```> python example_linux.py
    Just ran usercustomize, path: ['/home/Dropbox/programming/Python/lib/', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/home/martin/.local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages']


    ***** open_ports:
    [<serial.tools.list_ports_linux.SysFS object at 0x7bdb055f48b0>]
    Opening serial port /dev/ttyACM0
    closing UART
    Opening serial port /dev/ttyACM0
    args: ()
    kwargs: {'callbacks': [('*', <bound method Notifier.passOnNotification of <Sniffer(Thread-3, initial)>>)]}
    board ID: 0
    starting scan```

    This leaves behind the lock file, but the process of the pid of the lock file doesn't exist. Running a second time gives:

    ```

    > python example_linux.py
    Just ran usercustomize, path: ['/home/Dropbox/programming/Python/lib/', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/home/martin/.local/lib/python3.10/site-packages', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages']


    ***** open_ports:
    [<serial.tools.list_ports_linux.SysFS object at 0x7749c5a7c8b0>]
    Opening serial port /dev/ttyACM0
    Lockfile is stale. Overriding it..
    closing UART
    Opening serial port /dev/ttyACM0
    args: ()
    kwargs: {'callbacks': [('*', <bound method Notifier.passOnNotification of <Sniffer(Thread-3, initial)>>)]}
    board ID: 0
    starting scan```

    Note the "Lockfile is stale" which is from lines 48-49 of FileLock.py

    ``` logging.info("Lockfile is stale. Overriding it..")
    os.remove(lockfile)```

    Finally, line 96 of Devices.py ```if dev.name in [id, '"'+id+'"']:``` doesn't work if device.name has trailing  nulls which is the case for some commercial peripherals. Better would be ```if id in dev.name:```

    Summary: the most recent version of the SnifferAPI is not handling the lock files properly and has some edge cases where it doesn't work.

     

  • Thanks for all the details, forwarding this to our developer so that we can try to have this fixed

  • There is something else you could try in the mean time, the nRFUtil tool does use a has a ble-sniffer bootstrap and uses a different extcap. Might be worth a try. 

    https://github.com/NordicSemiconductor/nrfutil-package-index/tree/master/nr/fu 

  • Hi Jonathan,

    I have the same issue and found the following.

    The problem is two-fold:

    • Firstly, the nRF Sniffer module does not catch the SIGTERM from Wireshark and hence just terminates without any clean-up to the lock file. This leaves the lock file still populated with the PID of the terminated process. I have tested this by adding a signal handler for SIGTERM and confirmed that a SIGTERM is caught when stopping a Wireshark capture. Without this handler the Sniffer module simply terminates.
    • Secondly, Wireshark does not properly terminate the process by reading the exit code after sending SIGTERM to the Sniffer module. This leaves the process in the process table marked as <defunct> until Wireshark is exited.

    So when attempting another capture, the lock file still contains the PID of an existing process and will not overwrite it and the capture fails to start.

    As a workaround I have modified the lock() function in Filelock.py to check if the lockedpid is a zombie process as follows:

    def lock(port):
        if platform != 'linux':
            return
    
        tty = os.path.basename(port)
        lockfile = f'/var/lock/LCK..{tty}'
    
        lockedpid = lockpid(lockfile)
        if lockedpid:
            if lockedpid == os.getpid():
                return
    
            if psutil.pid_exists(lockedpid):
                if psutil.Process(lockedpid).status() != psutil.STATUS_ZOMBIE:
                    raise Exceptions.LockedException(f"Device {port} is locked")
                else:
                    logging.info("Lockfile is for a zombie process. Overriding it..")
                    os.remove(lockfile)
            else:
                logging.info("Lockfile is stale. Overriding it..")
                os.remove(lockfile)
    
        fd = open(lockfile, 'w')
        with open(lockfile, 'w') as fd:
            fd.write(f'{os.getpid():10}')

    Hopefully this helps anyone else with this issue.

    Regards,
    Paul

  • I retested with a fresh build of Wireshark 4.5.0 and with this version I am able to restart captures without restarting Wireshark. The Sniffer still terminates with SIGTERM but is no longer zombied. When the capture is restarted, the lockfile is considered stale and overwritten.

Related