1
0
mirror of https://github.com/esp8266/Arduino.git synced 2026-10-23 19:08:55 +03:00
Files
Clemens Kirchgatterer f946290ea9 Mock - clean up in UdpContext destructor (#9312)
* Fix possible crash in UdpContext host mocking.

I saw this crash in UdpContext.h happen after some hours of regular NTP requests....

```
[17:38:51] ADE:  voltage spike: phase A, factor=0.81, cycles=1
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) ClientContext::connect: ::connect(): Connection refused
[17:41:14] ADE:  voltage spike: phase A, factor=0.86, cycles=2
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) ClientContext::connect: ::connect(): Connection refused
[17:43:49] ADE:  voltage spike: phase B, factor=1.12, cycles=3
(mock) ClientContext::connect: ::connect(): Connection refused
(mock) =====> UdpServer port: 2390 <=====
[17:44:31] NTP:  waiting for response from '81.169.233.252' timed out

Program received signal SIGSEGV, Segmentation fault.
0x000055555556848c in std::_Function_base::_M_empty() const ()
(gdb) where
#0  0x000055555556848c in std::_Function_base::_M_empty() const ()
#1  0x00005555555685be in std::function<void ()>::operator bool() const ()
#2  0x00005555555684b8 in UdpContext::mock_cb() ()
#3  0x00005555555683af in check_incoming_udp() ()
#4  0x0000555555567fa6 in main ()
```

I tracked it down to UdpContext::mock_cb() which is calling a std::function callback that's been destroyed thus used-after-free. I believe  what happens is:
  1. UdpContext::unref() calls delete this when refcount hits 0 (line 56)
  2. The destructor (~UdpContext(), line 47) is empty — it never calls register_udp(_sock, nullptr) to remove itself from the global udps map
  3. check_incoming_udp() iterates udps, finds the dangling pointer, calls mock_cb() on freed memory
  4. _on_rx (a destroyed std::function) → segfault in _M_empty()

The disconnect() method already does the right thing (lines 78-84: closes socket + unregisters), but it's never called before the object is destroyed via  unref().

The fix is to make the destructor clean up properly.

I tested intensely, no crashes since.

* Format destructor for UdpContext for clarity

Fixes code-style CI.
2026-03-23 12:22:38 +03:00
..
2024-03-17 21:52:26 +03:00

Host Tests for Continuous Integration
-------------------------------------

	make FORCE32=0 OPTZ=-O0 CI

	(FORCE32=0: https://bugs.launchpad.net/ubuntu/+source/valgrind/+bug/948004)

Sketch emulation on host
------------------------

This environment let compile esp8266/Arduino sketches into native
environment.  Network (tcp, udp, including ssl and multicast) is linked to
local host interfaces.  WiFi is trivially emulated and reported as "just"
already connected and usable.

Currently network emulation is a complete rewrite of
WiFiClient+WiFiServer/ClientContext and WifiUdp/UdpContext using socket
posix API.  Further work will optionally propose native lwIP library
instead.

Serial UART0 and UART1 are emulated via stdin/stdout/stderr.  Therefore
stdin is connected to UART0(RX) and stdout is connected to UART0(TX).
UART1(TX) writes to stderr.  Reading from stdin happens in non-blocking
raw mode, that means each character is directly injected into the UART
FIFO without any buffering in the console.  The command line switch -c
can be used to stop the emulation from intercepting CTRL-C (SIGINT).

How to compile and run a sketch
-------------------------------

All results are stored in ./bin/ .

Show the core example list:
	make list


Build one example
	make D=1 ../../libraries/esp8266/examples/Blink/Blink
run it:
	./bin/Blink/Blink -h


Optional 'V=1' enables makefile verbosity
Optional 'D=1' enables core debug messages (same as Arduino IDE's tools/debug menu)
Optional 'OPTZ=-O2' will update gcc -O option (default is -Os, -D=1 implies -O0)
Optional 'FORCE32=0' will use native/default gcc (default is FORCE32=1 unless gcc-multilib is not detected)
Optional 'R="<options>"' (ex: R="-b -v") runs the executable with given options after build

Non exhaustive list of working examples:
	make D=1 ../../libraries/ESP8266WiFi/examples/udp/udp
	make D=1 ../../libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient
	make D=1 ../../libraries/ESP8266WebServer/examples/HelloServer/HelloServer
	make D=1 ../../libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer
	make D=1 ../../libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server
	make D=1 ../../libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation

Compile other sketches:
- library paths are specified using ULIBDIRS variable, separated by ':'
- call 'make path-to-the-sketch-file' to build (without its '.ino' extension):
- CAVEAT: functions must be declared *before* being called (arduino builder is not around)

	make D=1  ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2  /path/to/your/sketchdir/sketch/sketch
  or:
	ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2  make  D=1  /path/to/your/sketchdir/sketch/sketch

  or:
	export ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2
	export D=1
	export OPTZ=-O2
	make clean
	make /path/to/your/sketchdir/sketch/sketch
	./bin/sketch/sketch

Additional flags:
    make USERCFLAGS="-I some/where -I some/where/else" \
         USERCSOURCES="some/where/file1.c some/where/file2.c ..." \
         USERCXXSOURCES="some/where/file3.cpp some/where/file4.cpp ..." \
         USERLDFLAGS="-L some/where/around" \
         ...

Executable location is always in bin/. Once a sketch is compiled, just run it:
	bin/sketch/sketch

Options are available:
	-h
	-i eth0		bind servers to this interface (WIP)
	-l		bind Multicast to the above interface (WIP)
	-c		ignore CTRL-C (send it over serial device)
	-f		no throttle (possibly 100%CPU)
	-S		spiffs size in KBytes (default: 1024)
			(negative value will force mismatched size)

TODO
----
A lot.
Make fun, propose PRs.

- replace some "fprintf(stderr" with redirectable log functions
- spiffs in a file (done, need to initialize and check)
- EEPROM in a file (partly done)
- SDCARD on Host filesystem ? or in an image ?
- nice curses interface to display/change gpios ?
- display device emulation (like ssd1306)
- optionally use arduino-builder ?
- store sketch objects and binaries outside from the source directories (done for sketches)
- compile and use lwIP on host
- easily debug HTTP classes
- https://github.com/esp8266/Arduino/issues/1715
- gpio, currently:
  read as 0(digital) or 512(analog).
  output is printed on console.