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? 

Parents
  • Hi,

    Can you share what Wireshark version you have?

    And also have you asked Wireshark support? 

    Regards,
    Jonathan

  • I haven't tried Wireshark support because Wireshark appears to be working properly except when trying to communicate to nRF52804DK through /dev/ttyACM0 the second time which seems to be more of a Nordic sniffer issue, and my current guess I am working on opening /dev/ttyACM0 the second time is not working. In particular, I am suspect of devices = UART.find_sniffer() around line 160 in nrf_sniffer_ble.py; I haven't figured out how to set a breakpoint when running from wireshark. import pdb; pdb.set_trace() doesn't work, so I think I have to add a loop and attach with gdb or something like that?

    wireshark version:

    3.6.2 (Git v3.6.2 packaged as 3.6.2-2)

    Compiled (64-bit) using GCC 11.2.0, with Qt 5.15.2, with libpcap, with POSIX
    capabilities (Linux), with libnl 3, with GLib 2.71.2, with zlib 1.2.11, with Lua
    5.2.4, with GnuTLS 3.7.3 and PKCS #11 support, with Gcrypt 1.9.4, with MIT
    Kerberos, with MaxMind DB resolver, with nghttp2 1.43.0, with brotli, with LZ4,
    with Zstandard, with Snappy, with libxml2 2.9.12, with libsmi 0.4.8, with
    QtMultimedia, without automatic updates, with SpeexDSP (using system library),
    with Minizip.

    Running on Linux 6.5.0-28-generic, with 12th Gen Intel(R) Core(TM) i9-12900K
    (with SSE4.2), with 64016 MB of physical memory, with GLib 2.72.4, with zlib
    1.2.11, with Qt 5.15.3, with libpcap 1.10.1 (with TPACKET_V3), with c-ares
    1.18.1, with GnuTLS 3.7.3, with Gcrypt 1.9.4, with nghttp2 1.43.0, with brotli
    1.0.9, with LZ4 1.9.3, with Zstandard 1.4.8, with libsmi 0.4.8, with light
    display mode, without HiDPI, with LC_TYPE=en_US.UTF-8, binary plugins supported
    (19 loaded).

  • Are you using the latest version of the nRF sniffer for Bluetooth?  can be found here: https://www.nordicsemi.com/Products/Development-tools/nRF-Sniffer-for-Bluetooth-LE/Download?lang=en#infotabs 

    Could it be that the version you have Which extcap version are you using? Does the nrf_sniffer_ble.sh contain exec before $py3 $script_path/nrf_sniffer_ble.py "$@" (this is one of the differences between nRF Sniffer for Bluetooth LE 4.1.0 and 4.1.1).

    Regards,
    Jonathan

  • 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

Reply
  • 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

Children
Related