BBS:      TELESC.NET.BR
Assunto:  src/sftp/sftp_outcome.csrc/sbbs3/main.cpp sftp.cpp src/sftp/sftp.c sft
De:       Deuc¨
Data:     Sat, 25 Apr 2026 02:38:04 -0700
-----------------------------------------------------------
https://gitlab.synchro.net/main/sbbs/-/commit/800c8b09317e30a0868a4d10
Added Files:
	src/sftp/sftp_outcome.c
Modified Files:
	src/sbbs3/main.cpp sftp.cpp src/sftp/sftp.c sftp.h sftp_client.c sftp_server.c src/syncterm/sftp_browser.c sftp_queue.c ssh.c
Log Message:
sftp: replace last_error TLS hack with sftp{c,s}_outcome

The pthread_key_t TLS for sftpc_get_err was removed for portability in
2710c20e54, but that exposed a real race the TLS had been masking: the
three SyncTERM user threads (browser, uploader, downloader) sharing one
sftpc_state_t can clobber each other's last_error between op return
and sftpc_get_err call.

Reshape the API so per-op state lives in caller-supplied storage and
shared scalar state on the connection goes away.  New
struct sftp{c,s}_outcome carries:

  - err code (sftp_err_code_t -- flat enum of specific lib failure
    modes; SFTP_ERR_OK on success), valid when op returns false
  - result code (SSH_FX_* from server reply, client-side only),
    valid when op returns true
  - estr text accumulator with file:line prefixes per record, plus
    server-supplied SSH_FXP_STATUS messages as `Reply: "..."` lines

Bool contract:
  true  - op completed; act on result.  err/estr are diagnostic only.
  false - op didn't complete; result undefined.  Switch on err for
          retry decisions; show estr to the user.

Stack-allocated via SFTPC_OUTCOME_DECL(name, textsz) /
SFTPS_OUTCOME_DECL macros.  Pass NULL for "don't care", or sz=0 for
"codes but no text".  A single internal outcome_record_impl backs both
public record entry points so formatting/accumulation lives in one
place.  sftpc_outcome_reply formats server-supplied SSH_FXP_STATUS
text as `Reply: "msg" (lang)` lines, distinguishable from
file:line-prefixed lib-internal records.

Server side gets sftps_outcome too (no result field -- server supplies
the SSH_FX_* code rather than receiving it).  Threading covers
sftps_recv, sftps_send_packet/error/handle/data/name/attrs/extended_reply
and the static dispatch helpers.  sbbs3/main.cpp's sftps_recv sites
get real outcomes that log via lprintf on failure; sbbs3/sftp.cpp's
~100 sftps_send_* sites pass nullptr for now (existing lprintf
plumbing in the lib already logs the immediate context).

SyncTERM consumers (ssh.c, sftp_browser.c, sftp_queue.c) take real
outcomes.  The queue worker uses sftp_err_is_transient() to choose
between SFTP_JOB_QUEUED (retryable) and SFTP_JOB_FAILED for op-level
failures.  ssh.c's SSH_FX_EOF handling correctly lives on the
post-true branch.

set_thread_err / get_thread_err / sftpc_get_err / state->last_error
all gone.

Co-Authored-By: Claude Opus 4.7 (1M context) 
n
---
  mSynchronetn  hgVertrauen n hHome of Synchronet n gh[vert/cvs/bbs].synchro.net

-----------------------------------------------------------
[Voltar]