scheduler()'s defer unconditionally calls close(b.data). If the channel
was closed by the caller (or an upstream producer) instead of via the
normal Close()-sends-nil path, the receive on b.data returns ok == false,
scheduler returns, and the deferred close(b.data) then fires on an
already-closed channel:
panic: close of closed channel
reliably reproducible under the #3653 steps (manually closing b.data
while Start() is running).
Track whether we observed the external-close via a local
`externallyClosed` flag set in the `ok == false` branch. The defer
only closes b.data when that flag is false, i.e. when the scheduler
exited through the nil-message or ticker paths and still owns the
channel. No behaviour change on the graceful Close() path.
Fixes#3653
* pb
* fix: Modifying other fields while setting IsPrivateChat does not take effect
* fix: quote message error revoke
* refactoring scheduled tasks
* refactoring scheduled tasks
* refactoring scheduled tasks
* refactoring scheduled tasks
* refactoring scheduled tasks
* refactoring scheduled tasks
* upgrading pkg tools
* fix
* fix
* optimize log output
* feat: support GetLastMessage
* feat: support GetLastMessage
* feat: s3 switch
* feat: s3 switch
* fix: GetUsersOnline
* feat: SendBusinessNotification supported configuration parameters
* feat: SendBusinessNotification supported configuration parameters
* feat: SendBusinessNotification supported configuration parameters
* feat: seq conversion failed without exiting
* fix: DeleteDoc crash
* fix: fill send time
* fix: fill send time
* fix: crash caused by withdrawing messages from users who have left the group
* fix: user msg timestamp
* seq read config
* seq read config
* fix: the source message of the reference is withdrawn, and the referenced message is deleted
* feat: optimize the default notification.yml
* fix: shouldPushOffline
* fix: the sorting is wrong after canceling the administrator in group settings
* feat: Sending messages supports returning fields modified by webhook
* feat: Sending messages supports returning fields modified by webhook
* feat: Sending messages supports returning fields modified by webhook
* fix: oss specifies content-type when uploading
* fix: the version number contains a line break
* fix: the version number contains a line break
* feat: GetConversationsHasReadAndMaxSeq support pinned
* feat: GetConversationsHasReadAndMaxSeq support pinned
* feat: GetConversationsHasReadAndMaxSeq support pinned
* fix: transferring the group owner to a muted member, incremental version error
* feat: unified conversion code
* feat: update gomake
* fix: in standalone mode, the user online status is wrong
* fix: add permission check
* fix: add permission check
* refactor: cmd update.
* refactor: msg transfer refactor.
* refactor: msg transfer refactor.
* refactor: msg transfer refactor.
* fix: read prometheus port when flag set to enable and prevent failure during startup.
* fix: notification has counted unread counts bug fix.
* fix: merge opensource code into local.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* refactor: delete message and message batch use lua.
* fix: add protective measures against memory overflow.