How to solve write: broken pipe on websocket?

1.3k Views Asked by At

I'm making a progress bar for my program, and send it to client. The IPC I used is websocket. But I'm facing write: broken pipe when updating progress bar to the client. This error occurs after the first request. For example, on initial run of my app, when i perfrom request to the server, there is no error. But, when I perform another request, this error will occur.

Even though there is this error, but the progress bar is actually working despite the error (the progress bar is successfully sent to the client until 100%)

I'm using go fiber websocket as my server

// middleware
app.Use("/ws", func(c *fiber.Ctx) error {
  if websocket.IsWebSocketUpgrade(c) {
    c.Locals("allowed", true)
      return c.Next()
    }

    return fiber.ErrUpgradeRequired
})

// handler
func (s *downloaderService) progressBar(c *websocket.Conn) {
    channel := api.CreateChannel(c.Params("client"))
    done := make(chan bool)

    go func() {
        for {
            t, _, err := c.ReadMessage()
            if err != nil {
                log.Println("Error reading message:", err)
                return
            }

            if t == websocket.CloseMessage {
                done <- true
            }
        }
    }()

    for {
        select {
        case <-done:
            return
        case data, ok := <-channel.Subscribe():
            if !ok {
                return
            }

            progressBar := data.(downloader.Progressbar)

            payload, err := json.Marshal(progressBar)
            if err != nil {
                log.Println("Error marshalling data:", err)
                break
            }

            c.SetWriteDeadline(time.Now().Add(10 * time.Second))
            if err := c.WriteMessage(websocket.TextMessage, payload); err != nil {
                log.Println("Error sending progress data:", err)
                done <- true
            }
        }
    }
}

On the client, I'm using gorilla websocket


func main() {
    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, []os.Signal{syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGSTOP, os.Interrupt}...)

    ctx, cancel := context.WithCancel(context.Background())

    conn, res, err := websocket.DefaultDialer.DialContext(ctx, ws, nil)
    if err != nil {
        log.Fatalf("Error dialing websocket: %v. Status courlde %d", err, res.StatusCode)
        return
    }

    executeCommand(ctx)

    progressBar := progressbar()

    go func() {
        for {
            _, message, err := conn.ReadMessage()
            if err != nil {
                log.Println("Error reading message:", err)
                break
            }

            var progress progress
            if err := json.Unmarshal(message, &progress); err != nil {
                log.Println("Error unmarshalling message:", err)
                break
            }

            if progress.Done {
                truncateStore()
                cancel()
                break
            }

            progressBar.update(progress.Index, progress.Downloaded, progress.Size)
        }
    }()

    for {
        select {
        case <-ctx.Done():
            closeConn(ctx, conn)
            return
        case <-interrupt:
            stopDownload()
            closeConn(ctx, conn)
            return
        }
    }
}


func closeConn(ctx context.Context, conn *websocket.Conn) {
    if err := conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")); err != nil {
        log.Println("Error sending close signal to server:", err)
        return
    }

    select {
    case <-ctx.Done():
    case <-time.After(time.Second):
    }
}

The client is a CLI that will create request to the server. And when the progress bar is complete, it will be terminated.

Here is how it looked like enter image description here

Update

After reading the close message from client, I manage to get rid the broken pipe error. Instead, i got write: close sent

0

There are 0 best solutions below