Why does a gdb client fail to talk to its gdb server when started by this “expect” script

expectgdb

I'm building a continuous integration environment for a firmware codebase, programming an ARM Cortex M0 using a Segger JLink device and running tests on the target using gdb and Segger's RTT tool.

I have three processes I need to start from "expect":

  1. The gdb server. This listens for a connection from…
  2. The gdb client.
  3. Segger's RTT client logs output from the target to the host terminal so I can see how the tests are getting on.

I have "make" targets for each of these. When I run tests as a human, I have a terminal tab open for each. Run one by one in the terminal, they all run fine. However, when run by the following "expect" script, the gdb client will stop at the point at which it's supposed to be sending stuff to the gdb server. Why?

#!/usr/bin/expect

# Bike Tracker firmware/hardware test. For syntax, see "man expect".

# gdb server
spawn /Applications/SEGGER/JLink/JLinkGDBServer -device nrf51822 -if swd -speed 4000 -port 2331
expect {
  -ex "Waiting for GDB connection..."
}
sleep 1
send_user "\nexpect: gdb server running OK\n"

# gdb client
spawn ~/dev/gcc-arm-none-eabi-4_9-2015q1/bin/arm-none-eabi-gdb -x ./_build/.gdbinit ./_build/biketracker_app_s130.elf
sleep 2
set timeout 10
expect {
  -ex "(gdb)" {
    send "cont"
    send "cont"
  }
  -ex "Operation timed out" {
    send_user "expect: Timed out on gdb client. Did the server start OK?\n"
    exit 1
  }
  timeout {
    send_user "\nexpect: Timed out on gdb client output.\n"
    exit 1
  }
}
send_user "\nexpect: gdb client running OK\n"

# Segger RTT client
spawn /Applications/SEGGER/JLink/JLinkRTTClient -device nrf51822 -if swd -speed 4000
# If we do an RX operation on the modem, that takes 6s for the TX and about 30s for the RX.
set timeout 40
expect {
  -ex "END_OF_TEST" { exit 0 }
  eof { exit 0 }
  -ex "ASSERT" {
    send_user "\nexpect: A test failed. See RTT output for details.\n"
    exit 1
  }
  timeout {
    send_user "\nexpect: Timed out on RTT output.\n"
    exit 1
  }
}

Terminal output:

expect test.expect
spawn /Applications/SEGGER/JLink/JLinkGDBServer -device nrf51822 -if swd -speed 4000 -port 2331
SEGGER J-Link GDB Server V5.12f Command Line Version

JLinkARM.dll V5.12f (DLL compiled May 17 2016 16:04:43)

-----GDB Server start settings-----
GDBInit file:                  none
GDB Server Listening port:     2331
SWO raw output listening port: 2332
Terminal I/O port:             2333
Accept remote connection:      yes
Generate logfile:              off
Verify download:               off
Init regs on start:            off
Silent mode:                   off
Single run mode:               off
Target connection timeout:     0 ms
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 nrf51822
Target interface:              SWD
Target interface speed:        4000kHz
Target endian:                 little

Connecting to J-Link...
J-Link is connected.
Firmware: J-Link ARM V8 compiled Nov 28 2014 13:44:46
Hardware: V8.00
S/N: 268006243
OEM: SEGGER-EDU
Feature(s): FlashBP, GDB
Checking target voltage...
Target voltage: 3.04 V
Listening on TCP/IP port 2331
Connecting to target...Connected to target
Waiting for GDB connection...
expect: gdb server running OK
spawn ~/dev/gcc-arm-none-eabi-4_9-2015q1/bin/arm-none-eabi-gdb -x ./_build/.gdbinit ./_build/biketracker_app_s130.elf
GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150304-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin10 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./_build/biketracker_app_s130.elf...done.
0x0002ecf2 in rx_done_event (bytes=1 '\001', p_data=0x20002cec <rx_buffer> ",") at /Users/Eliot/dev/nRF5_SDK_11.0.0_89a8197/components/drivers_nrf/uart/nrf_drv_uart.c:631
631     m_cb.handler(&event,m_cb.p_context);
Loading section .text, size 0x1fbec lma 0x1b000

expect: Timed out on gdb client output.

Best Answer

The problem is probably that the gdb server output is being blocked because no one reads it, so the gdb client is also blocked. You can get expect to read and ignore the rest of the output from gdb with

expect_background eof exit

which makes the last spawned command continue with its output until end-of-file is read.

Related Question