Does anyone know how I can programmatically change the exit for each SockPort separately?
I didn't see this in control-spec. It's an interesting problem. If you have multiple SocksPort, and are using applications which are configured to use a specific SocksPort, there is a less-than-elegant solution. Specific to application traffic the Tor process maintains StreamID and CircuitID. You can use GETINFO stream-status to associate application StreamID with CircuitID. Applications can have multiple streams though so this could only help if application traffic can be identified using Target. Another possible way to identify an application stream is by using SETEVENTS STREAM then watch events having StreamStatus=NEW* from an application's SOURCE_ADDR. I suppose if the application only creates a single stream at a time it would also work.
You would also need to set the SessionGroup=INT isolation flag for each SocksPort. Give each SocksPort it's own INT group and applications won't share circuits. All the streams on a particular circuit will be associated with the applications using a SocksPort. It helps if only a single application uses each SocksPort. This makes the next part more useful (and practical).
Basically, CLOSECIRCUIT the CircuitID that an application (identified by a stream, circuit, target combination) is using. Now in the future that application will use a new general-purpose circuit (if __LeaveStreamsUnattached is default). The application needs to know it has to create a new connection. In other words, you're essentially interrupting any existing streams on the circuit, which is less elegant than issuing SIGNAL NEWNYM. In the latter case the existing streams aren't interrupted but rather new streams are attached to a new circuit. This might not be a big deal if you usually initiate a new connection from the application after SIGNAL NEWNYM.
It depends on the applications though. If the applications break in unpredicatable ways when existing connections are interrupted you should be prepared. You'll find the documentation for SessionGroup in Tor's manual and the rest in control-spec.
Is there a way to assign a separate control port to each SocksPort
Nope.
or tell the control port to change the exit node for a specific SocksPort
Nope.
I know it's not what you were hoping for but I hope that helps! You might also find txtorcon useful for this task.
-- leeroy