reduced chance of mutex related panic

This commit is contained in:
meera 2026-07-19 04:22:25 +03:00
parent c2551972a5
commit f921f53669
2 changed files with 28 additions and 19 deletions

2
.gitignore vendored
View File

@ -24,7 +24,7 @@ profile.cov
# Go workspace file # Go workspace file
go.work go.work
go.work.sum go.work.sum
stresser.go
# env file # env file
.env .env

45
main.go
View File

@ -777,8 +777,7 @@ func joinChannel(c *Client, name string) {
// reject duplicate join // reject duplicate join
if _, exists := ch.members[c.nick]; exists { if _, exists := ch.members[c.nick]; exists {
ch.mu.Unlock() ch.mu.Unlock()
c.fwrite(":server 443 %s %s %s :is already on channel\r\n", c.fwrite(":server 443 %s %s %s :is already on channel\r\n", c.nick, c.nick, name)
c.nick, c.nick, name)
return return
} }
// clean up stale empty nick // clean up stale empty nick
@ -788,28 +787,26 @@ func joinChannel(c *Client, name string) {
c.channels[name] = ch c.channels[name] = ch
ch.mu.Unlock() ch.mu.Unlock()
// echo JOIN to client
fmt.Fprintf(c.conn, ":%s JOIN %s\r\n", c.nick, name) fmt.Fprintf(c.conn, ":%s JOIN %s\r\n", c.nick, name)
// broadcast JOIN to others ch.mu.RLock()
for _, member := range ch.members { members := make([]*Client, 0, len(ch.members))
for _, m := range ch.members {
members = append(members, m)
}
ch.mu.RUnlock()
for _, member := range members {
if member != c { if member != c {
fmt.Fprintf(member.conn, ":%s JOIN %s\r\n", c.nick, name) fmt.Fprintf(member.conn, ":%s JOIN %s\r\n", c.nick, name)
} }
} }
// topic
if ch.description != "" { if ch.description != "" {
c.fwrite(":server 332 %s %s :%s\r\n", c.nick, name, ch.description) c.fwrite(":server 332 %s %s :%s\r\n", c.nick, name, ch.description)
} else { } else {
c.fwrite(":server 331 %s %s :No topic is set\r\n", c.nick, name) c.fwrite(":server 331 %s %s :No topic is set\r\n", c.nick, name)
} }
// names list
c.sendNames(ch) c.sendNames(ch)
// MODE if op
if ch.ops[c.nick] { if ch.ops[c.nick] {
for _, member := range ch.members { for _, member := range members {
member.fwrite(":server MODE %s +o %s\r\n", name, c.nick) member.fwrite(":server MODE %s +o %s\r\n", name, c.nick)
} }
} }
@ -831,7 +828,7 @@ func (c *Client) partChannel(name string) {
fmt.Fprintf(member.conn, ":%s PART %s\r\n", c.nick, name) fmt.Fprintf(member.conn, ":%s PART %s\r\n", c.nick, name)
} }
ch.mu.Unlock() ch.mu.Unlock()
broadcastNames(ch) //broadcastNames(ch)
} }
func addChannel(name string, description string) { func addChannel(name string, description string) {
name = normalizeChannelName(name) name = normalizeChannelName(name)
@ -899,7 +896,7 @@ func (c *Client) checkRegistration() {
} else { } else {
c.fwrite("%s :MOTD File is missing", c.nick) c.fwrite("%s :MOTD File is missing", c.nick)
} }
fmt.Fprintf(c.conn, ":server 376 %s :End of MOTD\r\n", c.nick) c.fwrite(":server 376 %s :End of MOTD\r\n", c.nick)
} }
} }
func reloadMOTD() { func reloadMOTD() {
@ -943,7 +940,7 @@ func showWho(c *Client, name string) {
for _, member := range ch.members { for _, member := range ch.members {
c.fwrite(":server 352 %s %s %s server %s H :0 %s\r\n", c.nick, name, member.host, member.nick, member.nick) c.fwrite(":server 352 %s %s %s server %s H :0 %s\r\n", c.nick, name, member.host, member.nick, member.nick)
} }
fmt.Fprintf(c.conn, ":server 315 %s %s :End of WHO list\r\n", c.nick, name) c.fwrite(":server 315 %s %s :End of WHO list\r\n", c.nick, name)
} }
func (c *Client) handleList() { func (c *Client) handleList() {
chMu.Lock() chMu.Lock()
@ -1017,18 +1014,30 @@ func (c *Client) cleanup() {
ch.mu.Lock() ch.mu.Lock()
delete(ch.members, c.nick) delete(ch.members, c.nick)
ch.mu.Unlock() ch.mu.Unlock()
for nick, member := range ch.members { ch.mu.RLock()
if nick != c.nick { snapshot := make([]*Client, 0, len(ch.members))
for _, member := range ch.members {
snapshot = append(snapshot, member)
}
ch.mu.RUnlock()
for _, member := range snapshot {
if member.nick != c.nick {
member.fwrite(":%s PART %s\r\n", c.nick, name) member.fwrite(":%s PART %s\r\n", c.nick, name)
} }
} }
delete(c.channels, name) delete(c.channels, name)
} }
cliMu.RLock() cliMu.RLock()
snapshot := make([]*Client, 0, len(clients))
for _, other := range clients { for _, other := range clients {
other.fwrite(":%s QUIT :Client disconnected\r\n", c.nick) snapshot = append(snapshot, other)
} }
cliMu.RUnlock() cliMu.RUnlock()
for _, other := range snapshot {
other.fwrite(":%s QUIT :Client disconnected\r\n", c.nick)
}
} }
func broadcastNames(ch *Channel) { func broadcastNames(ch *Channel) {