The problem was a stray process that was reading off of /dev/ttyS0. Weirdly, root could always take control over it, but as a normal user, it would show it as busy.
I detected this by using sudo fuser -k /dev/ttyS0.
sudo fuser -k /dev/ttyS0