Most development happens on the develop
branch, which is occasionally rebased + merged into master
when it’s not incredibly broken. When this happens, the develop
branch is usually pruned until I feel like making ‘unsafe’ changes again.
I may also name the branch develop+feature
if I’m developing multiple, or particularly unstable, features.
The intent is to keep master
relatively stable.
irctest
]() over it to make sure nothing’s severely broken.-unreleased
from the version number in irc/constants.go
.git tag v0.0.0 -m "Release v0.0.0"
(0.0.0
replaced with the real ver number).Once it’s built and released, you need to setup the new development version. To do so:
irc/constants.go
, update the version number to 0.0.1-unreleased
, where 0.0.1
is the previous release number with the minor field incremented by one (for instance, 0.9.2
-> 0.9.3-unreleased
)."Setup v0.0.1-unreleased devel ver"
.Unreleased changelog content
## Unreleased
New release of Oragono!
### Config Changes
### Security
### Added
### Changed
### Removed
### Fixed
vendor/
The vendor/
directory holds our dependencies. When we import new repos, we need to update this folder to contain these new deps. This is something that I’ll mostly be handling.
To update this folder:
cd
to Oragono folderdep ensure -update
cd vendor
"Updated packages"
cd ..
"vendor: Updated submodules"
This will make sure things stay nice and up-to-date for users.
Fuzzing can be useful. We don’t have testing done inside the IRCd itself, but this fuzzer I’ve written works alright and has helped shake out various bugs: irc_fuzz.py.
In addition, I’ve got the beginnings of a stress-tester here which is useful: https://github.com/DanielOaks/irc-stress-test
As well, there’s a decent set of ‘tests’ here, which I like to run Oragono through now and then: https://github.com/DanielOaks/irctest
To debug a hang, the best thing to do is to get a stack trace. Go’s nice, and you can do so by running this:
$ kill -ABRT <procid>
This will kill Oragono and print out a stack trace for you to take a look at.
Oragono involves a fair amount of shared state. Here are some of the main points:
client.Send
appends the message to a queue, which is then processed on a separate goroutine. It is always safe to call client.Send
.In consequence, there is a lot of state (in particular, server and channel state) that can be read and written from multiple goroutines. This state is protected with mutexes. To avoid deadlocks, mutexes are arranged in “tiers”; while holding a mutex of one tier, you’re only allowed to acquire mutexes of a strictly higher tier. The tiers are:
Channel.stateMutex
.ChannelManager.RWMutex
.Server.rehashMutex
, which prevents rehashes from overlapping.There are some mutexes that are “tier 0”: anything in a subpackage of irc
(e.g., irc/logger
or irc/connection_limits
) shouldn’t acquire mutexes defined in irc
.
We are using buntdb
for persistence; a buntdb.DB
has an RWMutex
inside it, with read-write transactions getting the Lock()
and read-only transactions getting the RLock()
. We haven’t completely decided where this lock fits into the overall lock model. For now, it’s probably better to err on the side of caution: if possible, don’t acquire new locks inside the buntdb
transaction, and be careful about what locks are held around the transaction as well.