Skip to content

Attach#67

Merged
rprtr258 merged 4 commits intomasterfrom
attach
Feb 18, 2025
Merged

Attach#67
rprtr258 merged 4 commits intomasterfrom
attach

Conversation

@rprtr258
Copy link
Owner

@rprtr258 rprtr258 commented Feb 18, 2025

solves #24

Summary by CodeRabbit

  • New Features
    • Introduced a utility that processes text input by reading lines and reporting their lengths, along with error notifications.
    • Added a command to attach to process input/output streams, allowing users to interact with a selected process based on identifiers.
    • Enhanced connection management to support multiple simultaneous outputs with improved logging and error handling for a more robust user experience.

@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a new Go program that reads input lines and prints their lengths, handling scan errors appropriately. It also adds a new _cmdAttach CLI command using the Cobra library to attach to a process by filtering and connecting via a Unix socket for bidirectional I/O. Additionally, a multiwriter type is added, and the shim functionality is enhanced to manage multiple network connections with improved logging and error handling.

Changes

File(s) Change Summary
e2e/tests/stdin/main.go New Go program that reads standard input line by line, prints the length of each line, and handles scanning errors.
internal/cli/attach.go, internal/cli/cli.go Added new _cmdAttach command in the CLI for attaching to processes; it filters processes, connects via Unix socket, and facilitates bidirectional I/O.
internal/cli/shim.go Introduced multiwriter type for handling multiple socket connections and updated implShim to accept connections with enhanced logging and robust error handling.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant AC as _cmdAttach
    participant PF as Process Filter
    participant US as Unix Socket
    U->>AC: Invoke attach [name|tag|id]
    AC->>PF: Filter processes (by name, tag, id)
    PF-->>AC: Return matching process
    alt Single process found
        AC->>US: Connect via Unix socket
        US-->>AC: Socket connected
        par Data Transfer
            AC->>U: Copy data from socket to stdout
            AC->>US: Forward stdin to socket
        end
    else
        AC-->>U: Return error (invalid matching)
    end
Loading
sequenceDiagram
    participant L as Listener (implShim)
    participant MW as Multiwriter
    participant PT as Pseudo-terminal
    participant C as Client Socket
    L->>L: Wait for incoming connection
    L->>C: Accept new socket connection
    L->>MW: Add connection to multiwriter
    PT->>MW: Data flows via TeeReader
    MW->>C: Write data to client socket
    note over MW, C: Handles errors and disconnects as needed
Loading

Poem

I'm a happy bunny on the run,
Hopping through code under the sun.
New commands and multiwriters in line,
Input and output all perfectly fine.
With every byte, my heart does leap—
A rabbit's delight, a change to keep! 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f86a8fe and 9a1b867.

📒 Files selected for processing (2)
  • internal/cli/attach.go (1 hunks)
  • internal/cli/shim.go (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
internal/cli/shim.go (4)

180-182: Consider concurrency protection.
Currently, this struct stores connections in a slice without synchronization. If multiple goroutines call Add/Write concurrently, data races may occur.


188-204: Avoid the naked return & verify logging of entire data.

  1. Returning with a naked return can reduce clarity. Consider explicitly returning (n, err).
  2. Logging the entire data string may expose sensitive content or inflate logs for large outputs.

Example fix:

 func (m *multiwriter) Write(p []byte) (n int, err error) {
-  return
+  return n, err
 }
🧰 Tools
🪛 GitHub Check: lint

[failure] 203-203:
naked return in func Write with 16 lines of code (nakedret)

🪛 golangci-lint (1.62.2)

203-203: naked return in func Write with 16 lines of code

(nakedret)


207-207: Refactor needed to reduce complexity.
The function implShim exceeds the recommended cognitive complexity threshold. Breaking it into smaller helper functions could improve readability and maintainability.

🧰 Tools
🪛 GitHub Check: lint

[failure] 207-207:
cognitive complexity 41 of func implShim is high (> 40) (gocognit)

🪛 golangci-lint (1.62.2)

207-207: cognitive complexity 41 of func implShim is high (> 40)

(gocognit)

🪛 GitHub Actions: CI

[error] 207-207: cognitive complexity 41 of func implShim is high (> 40) (gocognit)


208-208: Use professional comment style.
“because why the fuck not” is unprofessional. Consider rephrasing or removing such language.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b70df3 and f86a8fe.

📒 Files selected for processing (4)
  • e2e/tests/stdin/main.go (1 hunks)
  • internal/cli/attach.go (1 hunks)
  • internal/cli/cli.go (1 hunks)
  • internal/cli/shim.go (2 hunks)
🧰 Additional context used
🪛 GitHub Check: lint
internal/cli/shim.go

[failure] 207-207:
cognitive complexity 41 of func implShim is high (> 40) (gocognit)


[failure] 235-235:
cli.multiwriter is missing field writers (exhaustruct)


[failure] 231-231:
shadow: declaration of "err" shadows declaration at line 225 (govet)


[failure] 238-238:
shadow: declaration of "err" shadows declaration at line 225 (govet)


[failure] 203-203:
naked return in func Write with 16 lines of code (nakedret)

internal/cli/attach.go

[failure] 47-47:
shadow: declaration of "err" shadows declaration at line 41 (govet)

🪛 golangci-lint (1.62.2)
internal/cli/shim.go

207-207: cognitive complexity 41 of func implShim is high (> 40)

(gocognit)


235-235: cli.multiwriter is missing field writers

(exhaustruct)


231-231: shadow: declaration of "err" shadows declaration at line 225

(govet)


238-238: shadow: declaration of "err" shadows declaration at line 225

(govet)


203-203: naked return in func Write with 16 lines of code

(nakedret)

internal/cli/attach.go

47-47: shadow: declaration of "err" shadows declaration at line 41

(govet)

🪛 GitHub Actions: CI
internal/cli/shim.go

[error] 207-207: cognitive complexity 41 of func implShim is high (> 40) (gocognit)

🔇 Additional comments (16)
internal/cli/shim.go (10)

8-8: No concerns.


14-14: No concerns.


184-186: Potential data race in Add method.
Appending to the shared slice without synchronization might lead to a data race if Write is called concurrently.


214-214: No concerns.


224-224: No concerns.


229-229: No concerns.


234-234: No concerns.


235-236: No issues with initialization.
The multiwriter usage is correct.

🧰 Tools
🪛 GitHub Check: lint

[failure] 235-235:
cli.multiwriter is missing field writers (exhaustruct)

🪛 golangci-lint (1.62.2)

235-235: cli.multiwriter is missing field writers

(exhaustruct)


243-243: No concerns.


244-278: Verify concurrency on accepting multiple sockets.
Connections are appended and removed from m.writers in separate goroutines. Missing locks could cause data races or slice index errors under high concurrency.

e2e/tests/stdin/main.go (1)

1-19: Implementation looks correct.
The code straightforwardly reads lines and prints their lengths. No issues.

internal/cli/cli.go (1)

30-30: No concerns, command registration is straightforward.

internal/cli/attach.go (4)

1-14: LGTM!

The imports are well-organized, following the standard Go convention of grouping standard library, external, and internal packages.


16-25: LGTM!

The command setup follows Cobra best practices with clear usage patterns and intuitive aliases.


26-39: LGTM!

The filter setup is robust, combining multiple criteria and properly handling the case when exactly one process must be found.


56-58: LGTM!

The command finalization properly adds generic flags and follows Go's function literal pattern for immediate execution.

ptmxr := io.TeeReader(ptmx, conns)
go func() {
if _, err := io.Copy(outw, ptmx); err != nil {
if _, err := io.Copy(outw, ptmxr); err != nil {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix shadowed variable.
This local err shadows the err declared at line 225. Rename it to avoid confusion.

-if _, err := io.Copy(outw, ptmxr); err != nil {
+if _, copyErr := io.Copy(outw, ptmxr); copyErr != nil {
    log.Error().Err(copyErr)...
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if _, err := io.Copy(outw, ptmxr); err != nil {
if _, copyErr := io.Copy(outw, ptmxr); copyErr != nil {
log.Error().Err(copyErr)...
}
🧰 Tools
🪛 GitHub Check: lint

[failure] 238-238:
shadow: declaration of "err" shadows declaration at line 225 (govet)

🪛 golangci-lint (1.62.2)

238-238: shadow: declaration of "err" shadows declaration at line 225

(govet)

Comment on lines +41 to +54
conn, err := net.Dial("unix", filepath.Join(core.DirHome, proc.ID.String()+".sock"))
if err != nil {
return errors.Wrap(err, "connect to proc socket")
}

go func() {
_, err := io.Copy(os.Stdout, conn)
if err != nil {
log.Error().Err(err).Msg("copy stdout")
}
}()
_, err = io.Copy(conn, os.Stdin)
return errors.Wrap(err, "copy stdin")
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix variable shadowing and improve error handling.

The goroutine's error variable shadows the outer error variable. Additionally, the error handling for the stdout copy could be improved.

Apply this diff to fix the shadowing and improve error handling:

 			conn, err := net.Dial("unix", filepath.Join(core.DirHome, proc.ID.String()+".sock"))
 			if err != nil {
 				return errors.Wrap(err, "connect to proc socket")
 			}
 
+			errCh := make(chan error, 1)
 			go func() {
-				_, err := io.Copy(os.Stdout, conn)
-				if err != nil {
-					log.Error().Err(err).Msg("copy stdout")
-				}
+				_, copyErr := io.Copy(os.Stdout, conn)
+				errCh <- copyErr
 			}()
+
 			_, err = io.Copy(conn, os.Stdin)
-			return errors.Wrap(err, "copy stdin")
+			if err != nil {
+				return errors.Wrap(err, "copy stdin")
+			}
+
+			if copyErr := <-errCh; copyErr != nil {
+				return errors.Wrap(copyErr, "copy stdout")
+			}
+			return nil
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
conn, err := net.Dial("unix", filepath.Join(core.DirHome, proc.ID.String()+".sock"))
if err != nil {
return errors.Wrap(err, "connect to proc socket")
}
go func() {
_, err := io.Copy(os.Stdout, conn)
if err != nil {
log.Error().Err(err).Msg("copy stdout")
}
}()
_, err = io.Copy(conn, os.Stdin)
return errors.Wrap(err, "copy stdin")
},
conn, err := net.Dial("unix", filepath.Join(core.DirHome, proc.ID.String()+".sock"))
if err != nil {
return errors.Wrap(err, "connect to proc socket")
}
errCh := make(chan error, 1)
go func() {
_, copyErr := io.Copy(os.Stdout, conn)
errCh <- copyErr
}()
_, err = io.Copy(conn, os.Stdin)
if err != nil {
return errors.Wrap(err, "copy stdin")
}
if copyErr := <-errCh; copyErr != nil {
return errors.Wrap(copyErr, "copy stdout")
}
return nil
🧰 Tools
🪛 GitHub Check: lint

[failure] 47-47:
shadow: declaration of "err" shadows declaration at line 41 (govet)

🪛 golangci-lint (1.62.2)

47-47: shadow: declaration of "err" shadows declaration at line 41

(govet)

@rprtr258 rprtr258 merged commit 192cca3 into master Feb 18, 2025
3 checks passed
@rprtr258 rprtr258 deleted the attach branch February 18, 2025 18:43
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