Browse Source

Merge pull request #146 from slingamn/data_races.1

fix various data races, including 2 introduced by #139
tags/v0.9.2-beta
Daniel Oaks 6 years ago
parent
commit
5e9767c46d
5 changed files with 82 additions and 43 deletions
  1. 6
    5
      irc/client.go
  2. 22
    0
      irc/getters.go
  3. 1
    1
      irc/isupport.go
  4. 1
    1
      irc/nickname.go
  5. 52
    36
      irc/server.go

+ 6
- 5
irc/client.go View File

94
 	go socket.RunSocketWriter()
94
 	go socket.RunSocketWriter()
95
 	client := &Client{
95
 	client := &Client{
96
 		atime:          now,
96
 		atime:          now,
97
-		authorized:     server.password == nil,
97
+		authorized:     server.getPassword() == nil,
98
 		capabilities:   caps.NewSet(),
98
 		capabilities:   caps.NewSet(),
99
 		capState:       CapNone,
99
 		capState:       CapNone,
100
 		capVersion:     caps.Cap301,
100
 		capVersion:     caps.Cap301,
182
 		maxlenTags = 4096
182
 		maxlenTags = 4096
183
 	}
183
 	}
184
 	if client.capabilities.Has(caps.MaxLine) {
184
 	if client.capabilities.Has(caps.MaxLine) {
185
-		if client.server.limits.LineLen.Tags > maxlenTags {
186
-			maxlenTags = client.server.limits.LineLen.Tags
185
+		limits := client.server.getLimits()
186
+		if limits.LineLen.Tags > maxlenTags {
187
+			maxlenTags = limits.LineLen.Tags
187
 		}
188
 		}
188
-		maxlenRest = client.server.limits.LineLen.Rest
189
+		maxlenRest = limits.LineLen.Rest
189
 	}
190
 	}
190
 	return maxlenTags, maxlenRest
191
 	return maxlenTags, maxlenRest
191
 }
192
 }
679
 func (client *Client) Notice(text string) {
680
 func (client *Client) Notice(text string) {
680
 	limit := 400
681
 	limit := 400
681
 	if client.capabilities.Has(caps.MaxLine) {
682
 	if client.capabilities.Has(caps.MaxLine) {
682
-		limit = client.server.limits.LineLen.Rest - 110
683
+		limit = client.server.getLimits().LineLen.Rest - 110
683
 	}
684
 	}
684
 	lines := wordWrap(text, limit)
685
 	lines := wordWrap(text, limit)
685
 
686
 

+ 22
- 0
irc/getters.go View File

1
+// Copyright (c) 2017 Shivaram Lingamneni <slingamn@cs.stanford.edu>
2
+// released under the MIT license
3
+
4
+package irc
5
+
6
+func (server *Server) getISupport() *ISupportList {
7
+	server.configurableStateMutex.RLock()
8
+	defer server.configurableStateMutex.RUnlock()
9
+	return server.isupport
10
+}
11
+
12
+func (server *Server) getLimits() Limits {
13
+	server.configurableStateMutex.RLock()
14
+	defer server.configurableStateMutex.RUnlock()
15
+	return server.limits
16
+}
17
+
18
+func (server *Server) getPassword() []byte {
19
+	server.configurableStateMutex.RLock()
20
+	defer server.configurableStateMutex.RUnlock()
21
+	return server.password
22
+}

+ 1
- 1
irc/isupport.go View File

142
 
142
 
143
 // RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
143
 // RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
144
 func (client *Client) RplISupport() {
144
 func (client *Client) RplISupport() {
145
-	for _, tokenline := range client.server.isupport.CachedReply {
145
+	for _, tokenline := range client.server.getISupport().CachedReply {
146
 		// ugly trickery ahead
146
 		// ugly trickery ahead
147
 		client.Send(nil, client.server.name, RPL_ISUPPORT, append([]string{client.nick}, tokenline...)...)
147
 		client.Send(nil, client.server.name, RPL_ISUPPORT, append([]string{client.nick}, tokenline...)...)
148
 	}
148
 	}

+ 1
- 1
irc/nickname.go View File

34
 		return false
34
 		return false
35
 	}
35
 	}
36
 
36
 
37
-	if err != nil || len(nicknameRaw) > server.limits.NickLen || restrictedNicknames[nickname] {
37
+	if err != nil || len(nicknameRaw) > server.getLimits().NickLen || restrictedNicknames[nickname] {
38
 		client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, nicknameRaw, "Erroneous nickname")
38
 		client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, nicknameRaw, "Erroneous nickname")
39
 		return false
39
 		return false
40
 	}
40
 	}

+ 52
- 36
irc/server.go View File

182
 func (server *Server) setISupport() {
182
 func (server *Server) setISupport() {
183
 	maxTargetsString := strconv.Itoa(maxTargets)
183
 	maxTargetsString := strconv.Itoa(maxTargets)
184
 
184
 
185
+	server.configurableStateMutex.RLock()
186
+
185
 	// add RPL_ISUPPORT tokens
187
 	// add RPL_ISUPPORT tokens
186
-	server.isupport = NewISupportList()
187
-	server.isupport.Add("AWAYLEN", strconv.Itoa(server.limits.AwayLen))
188
-	server.isupport.Add("CASEMAPPING", casemappingName)
189
-	server.isupport.Add("CHANMODES", strings.Join([]string{Modes{BanMask, ExceptMask, InviteMask}.String(), "", Modes{UserLimit, Key}.String(), Modes{InviteOnly, Moderated, NoOutside, OpOnlyTopic, ChanRoleplaying, Secret}.String()}, ","))
190
-	server.isupport.Add("CHANNELLEN", strconv.Itoa(server.limits.ChannelLen))
191
-	server.isupport.Add("CHANTYPES", "#")
192
-	server.isupport.Add("ELIST", "U")
193
-	server.isupport.Add("EXCEPTS", "")
194
-	server.isupport.Add("INVEX", "")
195
-	server.isupport.Add("KICKLEN", strconv.Itoa(server.limits.KickLen))
196
-	server.isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(server.limits.ChanListModes)))
197
-	server.isupport.Add("MAXTARGETS", maxTargetsString)
198
-	server.isupport.Add("MODES", "")
199
-	server.isupport.Add("MONITOR", strconv.Itoa(server.limits.MonitorEntries))
200
-	server.isupport.Add("NETWORK", server.networkName)
201
-	server.isupport.Add("NICKLEN", strconv.Itoa(server.limits.NickLen))
202
-	server.isupport.Add("PREFIX", "(qaohv)~&@%+")
203
-	server.isupport.Add("RPCHAN", "E")
204
-	server.isupport.Add("RPUSER", "E")
205
-	server.isupport.Add("STATUSMSG", "~&@%+")
206
-	server.isupport.Add("TARGMAX", fmt.Sprintf("NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:%s,TAGMSG:%s,NOTICE:%s,MONITOR:", maxTargetsString, maxTargetsString, maxTargetsString))
207
-	server.isupport.Add("TOPICLEN", strconv.Itoa(server.limits.TopicLen))
188
+	isupport := NewISupportList()
189
+	isupport.Add("AWAYLEN", strconv.Itoa(server.limits.AwayLen))
190
+	isupport.Add("CASEMAPPING", casemappingName)
191
+	isupport.Add("CHANMODES", strings.Join([]string{Modes{BanMask, ExceptMask, InviteMask}.String(), "", Modes{UserLimit, Key}.String(), Modes{InviteOnly, Moderated, NoOutside, OpOnlyTopic, ChanRoleplaying, Secret}.String()}, ","))
192
+	isupport.Add("CHANNELLEN", strconv.Itoa(server.limits.ChannelLen))
193
+	isupport.Add("CHANTYPES", "#")
194
+	isupport.Add("ELIST", "U")
195
+	isupport.Add("EXCEPTS", "")
196
+	isupport.Add("INVEX", "")
197
+	isupport.Add("KICKLEN", strconv.Itoa(server.limits.KickLen))
198
+	isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(server.limits.ChanListModes)))
199
+	isupport.Add("MAXTARGETS", maxTargetsString)
200
+	isupport.Add("MODES", "")
201
+	isupport.Add("MONITOR", strconv.Itoa(server.limits.MonitorEntries))
202
+	isupport.Add("NETWORK", server.networkName)
203
+	isupport.Add("NICKLEN", strconv.Itoa(server.limits.NickLen))
204
+	isupport.Add("PREFIX", "(qaohv)~&@%+")
205
+	isupport.Add("RPCHAN", "E")
206
+	isupport.Add("RPUSER", "E")
207
+	isupport.Add("STATUSMSG", "~&@%+")
208
+	isupport.Add("TARGMAX", fmt.Sprintf("NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:%s,TAGMSG:%s,NOTICE:%s,MONITOR:", maxTargetsString, maxTargetsString, maxTargetsString))
209
+	isupport.Add("TOPICLEN", strconv.Itoa(server.limits.TopicLen))
208
 
210
 
209
 	// account registration
211
 	// account registration
210
 	if server.accountRegistration.Enabled {
212
 	if server.accountRegistration.Enabled {
216
 			}
218
 			}
217
 		}
219
 		}
218
 
220
 
219
-		server.isupport.Add("REGCOMMANDS", "CREATE,VERIFY")
220
-		server.isupport.Add("REGCALLBACKS", strings.Join(enabledCallbacks, ","))
221
-		server.isupport.Add("REGCREDTYPES", "passphrase,certfp")
221
+		isupport.Add("REGCOMMANDS", "CREATE,VERIFY")
222
+		isupport.Add("REGCALLBACKS", strings.Join(enabledCallbacks, ","))
223
+		isupport.Add("REGCREDTYPES", "passphrase,certfp")
222
 	}
224
 	}
223
 
225
 
224
-	server.isupport.RegenerateCachedReply()
226
+	server.configurableStateMutex.RUnlock()
227
+
228
+	isupport.RegenerateCachedReply()
229
+
230
+	server.configurableStateMutex.Lock()
231
+	server.isupport = isupport
232
+	server.configurableStateMutex.Unlock()
225
 }
233
 }
226
 
234
 
227
 func loadChannelList(channel *Channel, list string, maskMode Mode) {
235
 func loadChannelList(channel *Channel, list string, maskMode Mode) {
440
 // MOTD serves the Message of the Day.
448
 // MOTD serves the Message of the Day.
441
 func (server *Server) MOTD(client *Client) {
449
 func (server *Server) MOTD(client *Client) {
442
 	server.configurableStateMutex.RLock()
450
 	server.configurableStateMutex.RLock()
443
-	defer server.configurableStateMutex.RUnlock()
451
+	motdLines := server.motdLines
452
+	server.configurableStateMutex.RUnlock()
444
 
453
 
445
-	if len(server.motdLines) < 1 {
454
+	if len(motdLines) < 1 {
446
 		client.Send(nil, server.name, ERR_NOMOTD, client.nick, "MOTD File is missing")
455
 		client.Send(nil, server.name, ERR_NOMOTD, client.nick, "MOTD File is missing")
447
 		return
456
 		return
448
 	}
457
 	}
449
 
458
 
450
 	client.Send(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf("- %s Message of the day - ", server.name))
459
 	client.Send(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf("- %s Message of the day - ", server.name))
451
-	for _, line := range server.motdLines {
460
+	for _, line := range motdLines {
452
 		client.Send(nil, server.name, RPL_MOTD, client.nick, line)
461
 		client.Send(nil, server.name, RPL_MOTD, client.nick, line)
453
 	}
462
 	}
454
 	client.Send(nil, server.name, RPL_ENDOFMOTD, client.nick, "End of MOTD command")
463
 	client.Send(nil, server.name, RPL_ENDOFMOTD, client.nick, "End of MOTD command")
691
 
700
 
692
 		channel := server.channels.Get(casefoldedName)
701
 		channel := server.channels.Get(casefoldedName)
693
 		if channel == nil {
702
 		if channel == nil {
694
-			if len(casefoldedName) > server.limits.ChannelLen {
703
+			if len(casefoldedName) > server.getLimits().ChannelLen {
695
 				client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
704
 				client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
696
 				continue
705
 				continue
697
 			}
706
 			}
1257
 
1266
 
1258
 	// sanity checks complete, start modifying server state
1267
 	// sanity checks complete, start modifying server state
1259
 
1268
 
1260
-	server.name = config.Server.Name
1261
-	server.nameCasefolded = casefoldedName
1269
+	if initial {
1270
+		server.name = config.Server.Name
1271
+		server.nameCasefolded = casefoldedName
1272
+	}
1262
 	server.networkName = config.Network.Name
1273
 	server.networkName = config.Network.Name
1263
 
1274
 
1275
+	server.configurableStateMutex.Lock()
1264
 	if config.Server.Password != "" {
1276
 	if config.Server.Password != "" {
1265
 		server.password = config.Server.PasswordBytes()
1277
 		server.password = config.Server.PasswordBytes()
1266
 	} else {
1278
 	} else {
1267
 		server.password = nil
1279
 		server.password = nil
1268
 	}
1280
 	}
1281
+	server.configurableStateMutex.Unlock()
1269
 
1282
 
1270
 	// apply new PROXY command restrictions
1283
 	// apply new PROXY command restrictions
1271
 	server.proxyAllowedFrom = config.Server.ProxyAllowedFrom
1284
 	server.proxyAllowedFrom = config.Server.ProxyAllowedFrom
1372
 	}
1385
 	}
1373
 
1386
 
1374
 	// set server options
1387
 	// set server options
1388
+	server.configurableStateMutex.Lock()
1375
 	lineLenConfig := LineLenLimits{
1389
 	lineLenConfig := LineLenLimits{
1376
 		Tags: config.Limits.LineLen.Tags,
1390
 		Tags: config.Limits.LineLen.Tags,
1377
 		Rest: config.Limits.LineLen.Rest,
1391
 		Rest: config.Limits.LineLen.Rest,
1395
 	server.accountRegistration = &accountReg
1409
 	server.accountRegistration = &accountReg
1396
 	server.channelRegistrationEnabled = config.Channels.Registration.Enabled
1410
 	server.channelRegistrationEnabled = config.Channels.Registration.Enabled
1397
 
1411
 
1398
-	server.configurableStateMutex.Lock()
1399
 	server.defaultChannelModes = ParseDefaultChannelModes(config)
1412
 	server.defaultChannelModes = ParseDefaultChannelModes(config)
1400
 	server.configurableStateMutex.Unlock()
1413
 	server.configurableStateMutex.Unlock()
1401
 
1414
 
1402
 	// set new sendqueue size
1415
 	// set new sendqueue size
1403
 	if config.Server.MaxSendQBytes != server.MaxSendQBytes {
1416
 	if config.Server.MaxSendQBytes != server.MaxSendQBytes {
1417
+		server.configurableStateMutex.Lock()
1404
 		server.MaxSendQBytes = config.Server.MaxSendQBytes
1418
 		server.MaxSendQBytes = config.Server.MaxSendQBytes
1419
+		server.configurableStateMutex.Unlock()
1405
 
1420
 
1406
 		// update on all clients
1421
 		// update on all clients
1407
 		server.clients.ByNickMutex.RLock()
1422
 		server.clients.ByNickMutex.RLock()
1469
 	}
1484
 	}
1470
 
1485
 
1471
 	server.configurableStateMutex.Lock()
1486
 	server.configurableStateMutex.Lock()
1472
-	defer server.configurableStateMutex.Unlock()
1473
 	server.motdLines = motdLines
1487
 	server.motdLines = motdLines
1488
+	server.configurableStateMutex.Unlock()
1474
 	return nil
1489
 	return nil
1475
 }
1490
 }
1476
 
1491
 
1628
 	if len(msg.Params) > 0 {
1643
 	if len(msg.Params) > 0 {
1629
 		isAway = true
1644
 		isAway = true
1630
 		text = msg.Params[0]
1645
 		text = msg.Params[0]
1631
-		if len(text) > server.limits.AwayLen {
1632
-			text = text[:server.limits.AwayLen]
1646
+		awayLen := server.getLimits().AwayLen
1647
+		if len(text) > awayLen {
1648
+			text = text[:awayLen]
1633
 		}
1649
 		}
1634
 	}
1650
 	}
1635
 
1651
 

Loading…
Cancel
Save