I figured this out - replying to my own question in case it helps anyone.
Turns out this has to do with (undocumented?) interaction between CEP and AIP.
In my particular case, the following sequence occurs:
User clicks 'export' button on the CEP modal.
The plugin dispatches 'export' event to AIP, then closes the CEP modal with CSInterface().closeExtension();
AIP receives the 'export' event and pops sAIUser->PutFileDialog() to prompt for file save location
What I found was that the CEP closeExtension() call causes Illustrator to issue an abortModal() or something similar on the AIP side, causing any modal opened there to immediately close (this happens with native swift modal window, such as NSSavePanel, as well). If I keep the CEP modal open, than the PutFileDialog stays open as well.