Repository navigation
Commit d7d3db8
authored
fix(dedup): answer every command on the control socket, say proto=2 (#190)
* fix(dedup): answer every command on the control socket, say proto=2
The unix control socket answered ACK even when a START's counter reset
failed or an END's coverage was never sent, and closed with no answer
on a blank line or a command it could not parse. Keploy read each of
those as taken. A command that threw (a JaCoCo port out of range)
ended the accept loop, so every later test's command was refused.
Every command the SDK reads now gets one line before the close:
"ACK proto=2" when it was taken, "IGNORED proto=2" when not. A START
whose reset failed is ignored and so is its END; an END whose coverage
could not be collected or sent is ignored and still ends the test. A
command that throws is ignored and the server goes on. Only a
connection closed with nothing sent gets no answer.
proto=2 says this SDK answers every command it reads, so Keploy can
read a close with no answer as a command not taken: on macOS a
connection closed with its command unread gives the reader a plain
close, not an error. Agents that read only an IGNORED prefix, or no
answer at all, read "ACK proto=2" as ACK. The TCP transport is
unchanged.
The data socket path is a field, as the control socket's is, so the
rows can bind their own. The smoke test now requires the exact answer.
* fix(dedup): close the control socket on its own thread; IGNORED on TCP
stop() closed the unix control socket from the caller's thread and
returned at once, with the accept thread still running. junixsocket's
accept holds the socket's raw fd number, and when it finds the socket
file gone it closes that number. With start() right after stop(), that
number could already be the new server's socket, which was then closed
with its file still there: every later command was refused. The old
thread also deleted the socket file by path once it ended, so a start()
on the same path, as the default /tmp/coverage_control.sock always is,
lost its file, and every later command found no socket. Once junixsocket
had closed the socket under it, the accept loop went on: it spun a core,
logged without end, and isStarted() still said true.
Now only the accept thread closes its socket. stop() wakes that accept
with a connection of its own and waits up to 5 s for the thread to end,
so a command in flight is answered first; a start() after it waits for
that thread too. A socket closed under the server (its file deleted, or
bound again by another process) is said once and ends the server.
On the TCP transport, a START whose counter reset failed was answered
ACK, and its END sent the lines of the tests before it as this test's.
It is now answered "IGNORED <id>" and then ACK, as an END not taken is,
and its END is ignored too. A START whose reset threw (a JaCoCo port out
of range) ended the TCP thread, so no later command was answered; it is
now ignored and the connection goes on.
* fix(dedup): leave another server's socket file; IGNORED on a failed dump
junixsocket's delete on close deletes the socket file by path. When
another server had bound the control socket's path since (the file
deleted and bound again), stop() deleted that server's file. The SDK
now turns it off and deletes the file once its socket is closed, only
while the file is still the one it bound (the same device and inode).
On the TCP transport, an END whose JaCoCo dump failed sent an empty
COV, the frame of a test that ran no line of the app, so the collector
could not tell the two apart. It is now answered "IGNORED <id>" and
then ACK, as on the unix socket, and it ends the test.
stop() waits for the worker's thread through one interface for both
transports. When its wait is over with the thread still running, it
closes the socket, says so at WARNING and returns, where it waited a
second time before: a start() waits for that thread in turn. bind()
closes the socket it opened when it fails, so close() is only ever
called on a listening socket: it wakes the accept, and closes the
socket from the caller's thread only when the wake-up cannot connect.
The tests shorten the waits.
New rows: stop() during a command leaves the socket open to its own
thread; stop() after another server took the path ends the thread and
leaves that server's file; stop() after the socket file was deleted
ends at once; start() while the stopped worker still runs a command
refuses, and binds once that worker has ended; a TCP END whose dump
failed. The deleted-file row now also checks that it is said once.
Signed-off-by: slayerjain <shubhamkjain@outlook.com>1 parent 8f92303 commit d7d3db8
5 files changed
Lines changed: 909 additions & 99 deletions
File tree
- keploy-sdk/src
- main/java/io/keploy/dedup
- test/java/io/keploy/dedup
- scripts
0 commit comments