login terminates when its child (the logged-in user’s login shell) terminates. It could even exec the child without forking, replacing itself, but it needs to take care of PAM session clean-up, so it has to wait for its child instead. Once it terminates, getty or init (more generally, the init process) do some more clean-up (utmp etc.) and wait for a new login (if getty replaced itself with login, or exits when login terminates, the init process will start a new getty).
You’re right, under Linux at least, login is generally only used on virtual consoles (or real terminals connected via serial devices). Graphical display managers implement their own login mechanisms. You can run login inside a login shell, e.g. in a terminal emulator, with a little care (exec login); a long time ago, recursive login was used to change users, the equivalent of su nowadays.
Note that some shells do have a logout command, which is supposed to be used instead of exit to exit a login shell; in such shells, exit typically won’t exit from a login shell.