share / share/sharedb

Agent status should be changed immediately on calling close

Open
#221 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
6.5k
Forks
456
Avg merge
1d 5h
Merged PRs (30d)
5

Description

In the close function of an Agent, we call end on the stream.
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L54

And later on when event listeners for end event are called, it will call _cleanup in which we will change the status of the agent to closed.

https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L247
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L250

But in between this time interval, if any operation comes up, it will write to the closed stream and ERR_STREAM_WRITE_AFTER_END will be thrown. I'm able to reproduce this following way:

  1. Client A creates doc
  2. Client B subscribes to it and does some operations
  3. Some time later on, server wants to delete this doc due to some foo reason.
  4. Server closes all the agents connected to that doc.
  5. Server creates a new connection to the backend, fetches the same document and in the callback of the fetch, it sends delete operation on it.

What happens next:

  1. Backend receives delete request and forwards it to all the agents.
  2. Agent's status hasn't been changed to closed yet.
  3. Agent tries to write data to stream on which end had been called earlier and boom!

Stacktrace:

events.js:167
      throw er; // Unhandled 'error' event
      ^

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at writeAfterEnd (_stream_writable.js:243:12)
    at WebSocketJSONStream.Writable.write (_stream_writable.js:291:5)
    at Agent.send (/foobar/node_modules/sharedb/lib/agent.js:165:15)
    at Agent._sendOp (/foobar/node_modules/sharedb/lib/agent.js:181:8)
    at OpStream.<anonymous> (/foobar/node_modules/sharedb/lib/agent.js:103:11)
    at OpStream.emit (events.js:182:13)
    at OpStream.EventEmitter.emit (domain.js:442:20)
    at addChunk (_stream_readable.js:279:12)
    at readableAddChunk (_stream_readable.js:264:11)
    at OpStream.Readable.push (_stream_readable.js:219:10)
    at /foobar/node_modules/sharedb/lib/op-stream.js:38:14
    at Backend.trigger (/foobar/node_modules/sharedb/lib/backend.js:190:20)
    at Backend._sanitizeOp (/foobar/node_modules/sharedb/lib/backend.js:235:8)
    at OpStream.pushOp (/foobar/node_modules/sharedb/lib/op-stream.js:36:18)
    at MemoryPubSub.PubSub._emit (/foobar/node_modules/sharedb/lib/pubsub/index.js:94:26)
    at /foobar/node_modules/sharedb/lib/pubsub/memory.js:33:16
    at process._tickCallback (internal/process/next_tick.js:61:11)

So, I believe status of the agent should be changed in the close function itself.
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L58

@gkubisa If you believe what I have stated above is correct, I would like to see it merged in https://github.com/teamwork/sharedb

Thanks!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/agent.js at Agent.close, then compare the status update in _cleanup and the send path shown in the stack trace. Reproduce the close-then-operation sequence described in the issue and verify that an agent cannot write to the stream after close has been called.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.