Observe What an Immediate Exit Interrupts

LinuxBeginner
Practice Now

Introduction

The community download desk distributes North Pier field notes and a garden volunteer brief. Before closing the desk, a volunteer wants to let an already accepted download finish. The first implementation closes its connections immediately. You will first obtain a useful complete document, then observe exactly what an immediate stop interrupts.

Bring Go functions, handlers and error values, plus the goroutine/channel responsibilities from the previous two projects or equivalent experience. Process identity and SIGTERM are introduced here. The two named terminals are sessions on the same machine. Prepared observation tools record only the course's own built server and curl children; you do not need to learn their native trace format. Allow about 45 minutes, including reading and ordinary mistakes; this is an author estimate. Each unit starts independently.

Download One Complete Document

In this step, obtain a complete useful document and verify its actual bytes.

Start in Downloads. Both terminal entries only enter the existing workspace; opening a tab never rebuilds the scene. If you encounter an ordinary wrong-directory error, this visible command returns to the right location:

cd /home/labex/project/download-desk

Read the two original text files. They contain different practical material, not alternative names for the same sample. cat displays file content; it does not change the files.

cat documents/north-pier.txt documents/garden-route.txt

Keep these originals and all prepared files unchanged throughout this unit. You may build desk, start named observed attempts, and create downloads. This unit changes no Go source. Each later unit provides its own fresh copy.

Switch to Server. The Go executable is prepared at its absolute path. build compiles this package; . means the current package and -o desk names the built executable. Using a built binary makes its process identity explicit, unlike signaling a go run wrapper.

cd /home/labex/project/download-desk
/usr/local/go/bin/go build -o desk .

Start a named attempt. The supplied observer launches your binary and records its real process, HTTP requests, signals, and native exit; it does not implement graceful shutdown. first is an attempt name. It refuses an existing name so earlier evidence cannot be silently overwritten.

python3 desk.py serve first

Wait for Ready. Use Downloads for client requests. This terminal remains occupied until the original server exits. Its printed PID is the built Go child, not the observer. Leave Server running and switch to Downloads.

The prepared download client executes real curl, records its native process outcome, and saves its actual output. Its four arguments select the attempt, a new output label, a prepared document, and a per 32-byte delay in milliseconds. A delay of 0 is the ordinary fast sample. The label normal produces downloads/normal.txt.

python3 desk.py download first normal north-pier.txt 0

Expect Original curl native exit: 0. Zero means the transfer completed; it does not alone prove content. cmp compares the actual files byte for byte and prints nothing on equality. Read the saved useful document as well:

cmp documents/north-pier.txt downloads/normal.txt
cat downloads/normal.txt

If the client reports connection refusal, return to Server and read its existing output. Do not repeatedly launch another process on the same port. If Go reported a build error, correct the directory or compare the prepared file before building again. A new shell does not inherit another shell's variables, but the files and observed attempt are shared between these two sessions.

Stop the Exact Server During an Accepted Download

In this step, interrupt a genuinely accepted transfer and distinguish its client failure from the server exit.

Start in Downloads while Server still runs first. A process ID, or PID, identifies a currently running process, but the operating system can reuse it after exit. The observer also checks the executable path, the current user ID, and Linux start ticks from /proc to distinguish the original process. Only signal this course-owned built process. Do not use pkill, target the observer, or change platform processes or shell configuration.

SIGTERM is an ordinary request for a process to terminate. kill -TERM PID sends that request to one precise PID. It does not itself wait for downloads or prove the process finished. The prepared Go program receives this signal, calls immediate Close, and returns from main. That is the behavior you are about to observe, not a networking outage.

Read the rest of this step, including the expected failures and recovery, before starting the slow transfer. Then run the operation blocks in order; do not pause to learn the next concept while the finite request is running. The window is roughly half a minute for this document, not an unlimited wait.

Start a finite slow download in the background. & lets this shell accept the next command while the client runs; $! is the last background job's process ID, and the assignment saves that observer job so wait can later read its native outcome. The public 300ms delay occurs between 32-byte writes and gives you time to read and switch tabs; it is a controlled training transfer, not a performance measurement.

python3 desk.py download first interrupted north-pier.txt 300 & download_job=$!

Before stopping anything, ask the observer to read the already recorded native request. This command does not send a substitute request or a signal. It must report that the original server accepted this actual client and both identities are still present. Default curl may buffer small file writes, so a temporarily empty output file does not mean the request never started.

python3 desk.py accepted first interrupted

Now obtain and inspect the original identity. $(...) stores this command's printed PID in a shell variable; the quoted "$server_pid" later supplies it as one argument. The helper refuses a stale PID/start/executable/UID combination.

server_pid=$(python3 desk.py pid first)
python3 desk.py identity first

Send the precise signal only after the accepted-request observation:

kill -TERM "$server_pid"

Read the original client result. wait waits for this shell's background job. This next command is expected to return 18, accompanied by curl's message about missing bytes. That is a completed observation of a failed transfer, not a command you should hide with a success marker.

wait "$download_job"

echo $? immediately displays the preceding native status, expected 18. A later successful cat would replace that shell status, so read it immediately:

echo $?
cat downloads/interrupted.txt

Compare with the original:

cmp documents/north-pier.txt downloads/interrupted.txt

This comparison is expected to return 1 and report that the partial file ended early. The received text begins with real North Pier content but is incomplete. A matching filename or a nonempty file would therefore be insufficient evidence of a useful complete download. Switch to Server and read Original server native exit: 0. A normally exited server can still have interrupted its clients.

Return to Downloads and retain both results. The course check only reads your existing observations and actual files; it never stops a live process or creates the missing interruption for you.

If you waited long enough that the slow transfer completed before signaling, do not call that an interruption. Read its native 0 result and compare its full bytes; preserve it. If first is still running, start the same slow command with a new label such as interrupted2, save its new background job, and use that same label in accepted before signaling. If the original server already exited, switch to Server and explicitly start a new attempt such as retry1, preserving the old attempt; then use that attempt name and a new output label in the download, accepted, pid, and identity commands. The check accepts these new names. Repeat the real observation rather than copying a partial file. A finished or unknown transfer is not permission to send another signal to a recycled PID.

Here is a complete retry on the same still-running first attempt. Use it only after the old client has actually finished; preserve downloads/interrupted.txt. Read all these blocks before starting. The new label produces a separate output:

python3 desk.py download first interrupted2 north-pier.txt 300 & download_job=$!
python3 desk.py accepted first interrupted2
server_pid=$(python3 desk.py pid first)
python3 desk.py identity first
kill -TERM "$server_pid"

The next wait is again expected to return 18; read it immediately, then compare the new actual partial file (comparison expected1):

wait "$download_job"
echo $?
cmp documents/north-pier.txt downloads/interrupted2.txt

If first already exited, start a distinct attempt in Server instead:

python3 desk.py serve retry1

After its ready message, use this complete sequence in Downloads, with a third fresh output label:

python3 desk.py download retry1 interrupted3 north-pier.txt 300 & download_job=$!
python3 desk.py accepted retry1 interrupted3
server_pid=$(python3 desk.py pid retry1)
python3 desk.py identity retry1
kill -TERM "$server_pid"
wait "$download_job"
echo $?

The wait should return 18. Preserve the actual output and verify it is incomplete (comparison expected1):

cmp documents/north-pier.txt downloads/interrupted3.txt

Finish with the original stopped desk and retained results. Your normal downloaded file is already complete and remains available to read; do not leave a replacement listener running before the check. The next independent unit teaches how to preserve active transfers.

Summary

You observed a real complete download, then connected an interrupted transfer to a precise stop of its original server. A refused connection, a partial transfer, and a normal process exit describe different facts.