diff --git a/ci/test.sh b/ci/test.sh
index 9cf982a594b4a97ff9d5f4101c2ba24697d8c223..f08c2ddf8dd2f637fabfc7b7ef569168028e471b 100755
--- a/ci/test.sh
+++ b/ci/test.sh
@@ -17,7 +17,7 @@ if [[ $CI ]]; then
   pip install -qqq autobahntestsuite
 fi
 
-go test -race -coverprofile=ci/out/coverage.prof --vet=off -bench=. -coverpkg=./... ./...
+go test -race -coverprofile=ci/out/coverage.prof --vet=off -bench=. -coverpkg=./... "$@" ./...
 go tool cover -func=ci/out/coverage.prof
 
 if [[ $CI ]]; then
diff --git a/websocket.go b/websocket.go
index 47db5f1882ac70104e146c18cae43efdbc7fbb7b..80d5511a10fbbe0a3cf0a98324938ba413fa1cf6 100644
--- a/websocket.go
+++ b/websocket.go
@@ -41,9 +41,10 @@ type Conn struct {
 	closer   io.Closer
 	client   bool
 
-	closeOnce sync.Once
-	closeErr  error
-	closed    chan struct{}
+	closeOnce    sync.Once
+	closeErrOnce sync.Once
+	closeErr     error
+	closed       chan struct{}
 
 	// writeMsgLock is acquired to write a data message.
 	writeMsgLock chan struct{}
@@ -115,11 +116,17 @@ func (c *Conn) Subprotocol() string {
 	return c.subprotocol
 }
 
+func (c *Conn) setCloseErr(err error) {
+	c.closeErrOnce.Do(func() {
+		c.closeErr = xerrors.Errorf("websocket closed: %w", err)
+	})
+}
+
 func (c *Conn) close(err error) {
 	c.closeOnce.Do(func() {
 		runtime.SetFinalizer(c, nil)
 
-		c.closeErr = xerrors.Errorf("websocket closed: %w", err)
+		c.setCloseErr(err)
 		close(c.closed)
 
 		// Have to close after c.closed is closed to ensure any goroutine that wakes up
@@ -304,7 +311,11 @@ func (c *Conn) handleControl(ctx context.Context, h header) error {
 			c.Close(StatusProtocolError, "received invalid close payload")
 			return xerrors.Errorf("received invalid close payload: %w", err)
 		}
-		c.writeClose(b, xerrors.Errorf("received close frame: %w", ce))
+		// This ensures the closeErr of the Conn is always the received CloseError
+		// in case the echo close frame write fails.
+		// See https://github.com/nhooyr/websocket/issues/109
+		c.setCloseErr(xerrors.Errorf("received close frame: %w", ce))
+		c.writeClose(b, nil)
 		return c.closeErr
 	default:
 		panic(fmt.Sprintf("websocket: unexpected control opcode: %#v", h))