Skip to content

Conversation

@abakum
Copy link
Contributor

@abakum abakum commented Dec 26, 2025

#943
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
...
c, err:=NewCtx(ctx, Options{...})
...
go func() {
c.Send(...)
donechan <- true
}()
go func() {
<-cancelchan
cancel()
}()
...
go func() {
c.Receive()
donechan <- true
}()
go func() {
<-cancelchan
cancel()
}()
...

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds context support for GUI-driven clients and relays, enabling graceful cancellation of long-running operations in the croc file transfer application. The implementation introduces context-aware versions of key functions and proper cleanup mechanisms.

Changes:

  • Added context-aware file hashing functionality (HashFileCtx) that can be canceled mid-operation
  • Implemented context-based TCP server management with graceful shutdown support
  • Integrated context cancellation throughout the croc client lifecycle (Send/Receive operations)

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
src/utils/ctx.go New file implementing context-aware file hashing with cancellation support
src/utils/utils_test.go Comprehensive tests for HashFileCtx covering cancellation scenarios
src/utils/utils.go Minor fallback improvement for GetLocalIPs
src/tcp/ctx.go Context management for TCP server with graceful shutdown
src/tcp/tcp.go Refactored TCP server to use context-based lifecycle management
src/tcp/tcp_test.go Tests for context-aware TCP server and various edge cases
src/croc/ctx.go Context support for croc client operations
src/croc/croc.go Integrated context cancellation throughout client lifecycle
src/croc/croc_test.go Tests for context cancellation in various transfer scenarios
Comments suppressed due to low confidence (1)

src/utils/ctx.go:1

  • There's a race condition here. The context could be canceled between the select statement (line 46) and the ReadAt call (line 50), or between the ReadAt call and the context check (line 51). While this won't cause corruption, it creates inconsistent behavior. Consider using a non-blocking select after the read to check if cancellation occurred during the operation.
// ctx.go

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

bar.Add(0)
}

b, err := imopartial.SumSectionReader(sr)
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable imopartial is not defined in this file. It's defined in utils.go but not imported here. Either import it from utils.go by making it accessible, or define it locally in ctx.go.

Copilot uses AI. Check for mistakes.
bar.Add(0) // Start the spinner
}

b, err := imofull.SumSectionReader(sr)
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable imofull is not defined in this file. It's defined in utils.go but not imported here. Either import it from utils.go by making it accessible, or define it locally in ctx.go.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +32
// stopRoomCleanup chan struct{}
// replaced by stop ctx.go
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented-out code rather than leaving it with a note. The version control system preserves this history.

Copilot uses AI. Check for mistakes.
s.roomTTL = DEFAULT_ROOM_TTL
s.debugLevel = DEFAULT_LOG_LEVEL
s.stopRoomCleanup = make(chan struct{})
// s.stopRoomCleanup = make(chan struct{}) replaced by stop
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented-out code rather than leaving it with a note. The version control system preserves this history.

Suggested change
// s.stopRoomCleanup = make(chan struct{}) replaced by stop

Copilot uses AI. Check for mistakes.
defer s.stop.wg.Done()
s.deleteOldRooms()
}()
// defer s.stopRoomDeletion()
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented-out code rather than leaving it with a note. The version control system preserves this history.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +70
func (c *ctxFile) Seek(offset int64, whence int) (n int64, err error) {
select {
case <-c.ctx.Done():
return 0, c.ctx.Err()
default:
n, err = c.f.Seek(offset, whence)
if c.ctx.Err() != nil {
return 0, c.ctx.Err()
}
return n, err
}
}
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a race condition here. The context could be canceled between the select statement (line 60) and the Seek call (line 64), or between the Seek call and the context check (line 65). While this won't cause corruption, it creates inconsistent behavior. Consider using a non-blocking select after the seek to check if cancellation occurred during the operation.

Copilot uses AI. Check for mistakes.
Comment on lines +149 to +160
go func() {
dc := &net.Dialer{
Timeout: 100 * time.Millisecond,
}
if conn, err := dc.DialContext(s.stop.ctx, network, addr); err == nil {
log.Debugf("started TCP server on %s", addr)
conn.Close()
} else {
log.Errorf("started TCP server on %s : %v", addr, err)
s.stop.Cancel()
}
}()
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This goroutine is fired-and-forgotten without any synchronization. If the main function returns before this goroutine completes, it may not execute fully. Consider adding this to the WaitGroup or using a synchronization mechanism to ensure proper cleanup.

Copilot uses AI. Check for mistakes.
Comment on lines +1434 to +1443
defer func() {
if r := recover(); r != nil {
if c.stop.gui {
log.Errorf("panic: %v", r)
c.stop.Cancel()
} else {
panic(r)
}
}
}()
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing panics in GUI mode can hide serious bugs. Consider logging the full stack trace with debug.Stack() to aid debugging, and potentially returning an error from this function instead of silently recovering.

Copilot uses AI. Check for mistakes.
Comment on lines +2061 to +2070
defer func() {
if r := recover(); r != nil {
if c.stop.gui {
log.Errorf("panic: %v", r)
c.stop.Cancel()
} else {
panic(r)
}
}
}()
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing panics in GUI mode can hide serious bugs. Consider logging the full stack trace with debug.Stack() to aid debugging, and potentially returning an error from this function instead of silently recovering.

Copilot uses AI. Check for mistakes.
Comment on lines +2161 to +2168
if r := recover(); r != nil {
if c.stop.gui {
log.Errorf("panic: %v", r)
c.stop.Cancel()
} else {
panic(r)
}
}
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing panics in GUI mode can hide serious bugs. Consider logging the full stack trace with debug.Stack() to aid debugging, and potentially returning an error from this function instead of silently recovering.

Copilot uses AI. Check for mistakes.
@abakum
Copy link
Contributor Author

abakum commented Jan 16, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant