Slide 1

Slide 1 text

Sweetie  Bot I  MADE  AN  ANTI-­‐SPAM  BOT  FOR  DISCORD NOW  I  REGRET  EVERYTHING

Slide 2

Slide 2 text

Introduction Erik  McClure  aka  Cloud  Hop From  Redmond,  Washington Works  At  Microsoft  (again) Made  Pony  Clicker  (for  some  reason) Sometimes  writes  music  and  fanfiction http://cloudhop.horse twitter:  @blackhole0173

Slide 3

Slide 3 text

Discord § A  new  chat  and  voice  client  for  gamers  that  emerged  in  late  2015. § Way  better  than  Skype  in  almost  every  way § Honestly  this  slide  should  probably  be  removed  because  everyone  knows  what  Discord  is.

Slide 4

Slide 4 text

Bot  Origins § When  Discord  first  emerged,  My  Little  Pony  chats  were  targeted  by  trolls § Building  an  anti-­‐spam  bot  required  using  a  reversed  engineered,  unsupported  api § The  API  itself  would  often  throw  spurious  errors  or  simply  fail  to  perform  actions § Sweetie  Bot  exploded  to  1000+  servers  with  hundreds  of  thousands  of  users § She  is  still  the  top  google  result  for  “discord  anti-­‐spam  bot”,  for  some  reason. § The  old  code  intended  to  deal  with  a  few  hundred  servers  simply  couldn’t  deal  with  this § Last  time,  I  talked  about  the  database  deadlock  issues.

Slide 5

Slide 5 text

Then  This  Happened

Slide 6

Slide 6 text

Debugging  With  Cloud  Hop § This  time,  let’s  talk  about  Go  deadlocks. § Discordgo is  either  single-­‐threaded  or  launches  a  new  goroutine for  every  event. § Single-­‐threaded  is  bad  because  of  a  rate-­‐limiting  edge  case. § Multi-­‐threaded  is  bad  because  discordgo is  awful. § Sweetie’s  method  of  silencing  requires  solving  a  race-­‐condition § In  this  case,  doing  things  the  right  way  was  a  bad  idea.   § Sweetie’s  deadlocking  was  so  bad  I  built  a  deadlock  detector § It  literally  turns  the  bot  off  and  on  again  if  something  goes  wrong

Slide 7

Slide 7 text

Fix  Code  By  Introducing  Race  Conditions! § For  the  love  of  all  that  is  holy,  NEVER  ACTUALLY  DO  THIS. § The  deadlock  is  caused  by  DiscordGo’s terrible  architecture. § One  state  object  holds  state  for  all  servers  and  has  only  one  lock § Trying  to  run  discordgo using  Go’s  data  race  detector  tells  you  that  everything  is  a  data  race § Discordgo assumes  that  you  never  take  write  lock  on  the  state  in  an  event  handler. § This  isn’t  actually  mentioned  anywhere § Fixing  this  requires  rewriting  the  entire  library  from  the  ground  up § Even  just  fixing  this  specific  subcase  would  require  a  pull  request. § So  I  just  assign  the  new  slice  to  the  old  slice  without  a  lock  and  hope  it  doesn’t  crash § It  worked

Slide 8

Slide 8 text

Lessons  Learned § Discordgo is  a  bad  library § Making  this  bot  was  a  mistake § The  only  way  to  fix  this  is  to  either  build  a   new  Go  API  library  or  use  another  language § But  the  discord  rate-­‐limit  edge  case  makes  this  a   giant  pain  in  the  ass  in  any  language. § Most  of  this  could  probably  have  been   avoided  with  more  granular  locking. § Unfortunately  discordgo has  more  fundamental   architectural  issues.