3838#include < io.h>
3939#endif
4040
41- extern " C" const void *swift_ASTGen_getCompilerPluginCapability (void *handle);
42- extern " C" void swift_ASTGen_destroyCompilerPluginCapability (void *value);
43-
4441using namespace swift ;
4542
4643llvm::Expected<void *> PluginRegistry::loadLibraryPlugin (StringRef path) {
@@ -74,14 +71,14 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
7471 }
7572
7673 // See if the plugin is already loaded.
77- auto &plugin = LoadedPluginExecutables[path];
78- if (plugin ) {
74+ auto &storage = LoadedPluginExecutables[path];
75+ if (storage ) {
7976 // See if the loaded one is still usable.
80- if (plugin ->getLastModificationTime () == stat.getLastModificationTime ())
81- return plugin .get ();
77+ if (storage ->getLastModificationTime () == stat.getLastModificationTime ())
78+ return storage .get ();
8279
8380 // The plugin is updated. Close the previously opened plugin.
84- plugin = nullptr ;
81+ storage = nullptr ;
8582 }
8683
8784 if (!llvm::sys::fs::exists (stat)) {
@@ -94,8 +91,35 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
9491 " not executable" );
9592 }
9693
94+ auto plugin = std::unique_ptr<LoadedExecutablePlugin>(
95+ new LoadedExecutablePlugin (path, stat.getLastModificationTime ()));
96+
97+ // Launch here to see if it's actually executable, and diagnose (by returning
98+ // an error) if necessary.
99+ if (auto error = plugin->spawnIfNeeded ()) {
100+ return std::move (error);
101+ }
102+
103+ storage = std::move (plugin);
104+ return storage.get ();
105+ }
106+
107+ llvm::Error LoadedExecutablePlugin::spawnIfNeeded () {
108+ if (Process) {
109+ // See if the loaded one is still usable.
110+ if (!Process->isStale )
111+ return llvm::Error::success ();
112+
113+ // NOTE: We don't check the mtime here because 'stat(2)' call is too heavy.
114+ // PluginRegistry::loadExecutablePlugin() checks it and replace this object
115+ // itself if the plugin is updated.
116+
117+ // The plugin is stale. Discard the previously opened process.
118+ Process.reset ();
119+ }
120+
97121 // Create command line arguments.
98- SmallVector<StringRef, 4 > command{path };
122+ SmallVector<StringRef, 4 > command{ExecutablePath };
99123
100124 // Apply sandboxing.
101125 llvm::BumpPtrAllocator Allocator;
@@ -107,29 +131,36 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
107131 return llvm::errorCodeToError (childInfo.getError ());
108132 }
109133
110- plugin = std::unique_ptr<LoadedExecutablePlugin>(new LoadedExecutablePlugin (
111- childInfo->Pid , stat.getLastModificationTime (),
112- childInfo->ReadFileDescriptor , childInfo->WriteFileDescriptor ));
134+ Process = std::unique_ptr<PluginProcess>(
135+ new PluginProcess (childInfo->Pid , childInfo->ReadFileDescriptor ,
136+ childInfo->WriteFileDescriptor ));
137+
138+ // Call "on reconnect" callbacks.
139+ for (auto *callback : onReconnect) {
140+ (*callback)();
141+ }
113142
114- return plugin. get ();
143+ return llvm::Error::success ();
115144}
116145
117- LoadedExecutablePlugin::LoadedExecutablePlugin (
118- llvm::sys::procid_t pid, llvm::sys::TimePoint<> LastModificationTime,
119- int inputFileDescriptor, int outputFileDescriptor)
120- : pid(pid), LastModificationTime(LastModificationTime),
121- inputFileDescriptor(inputFileDescriptor),
146+ LoadedExecutablePlugin::PluginProcess::PluginProcess (llvm::sys::procid_t pid,
147+ int inputFileDescriptor,
148+ int outputFileDescriptor)
149+ : pid(pid), inputFileDescriptor(inputFileDescriptor),
122150 outputFileDescriptor(outputFileDescriptor) {}
123151
124- LoadedExecutablePlugin::~LoadedExecutablePlugin () {
152+ LoadedExecutablePlugin::PluginProcess::~PluginProcess () {
125153 close (inputFileDescriptor);
126154 close (outputFileDescriptor);
155+ }
127156
157+ LoadedExecutablePlugin::~LoadedExecutablePlugin () {
128158 // Let ASTGen to cleanup things.
129159 this ->cleanup ();
130160}
131161
132- ssize_t LoadedExecutablePlugin::read (void *buf, size_t nbyte) const {
162+ ssize_t LoadedExecutablePlugin::PluginProcess::read (void *buf,
163+ size_t nbyte) const {
133164 ssize_t bytesToRead = nbyte;
134165 void *ptr = buf;
135166
@@ -154,7 +185,8 @@ ssize_t LoadedExecutablePlugin::read(void *buf, size_t nbyte) const {
154185 return nbyte - bytesToRead;
155186}
156187
157- ssize_t LoadedExecutablePlugin::write (const void *buf, size_t nbyte) const {
188+ ssize_t LoadedExecutablePlugin::PluginProcess::write (const void *buf,
189+ size_t nbyte) const {
158190 ssize_t bytesToWrite = nbyte;
159191 const void *ptr = buf;
160192
@@ -187,15 +219,17 @@ llvm::Error LoadedExecutablePlugin::sendMessage(llvm::StringRef message) const {
187219 // Write header (message size).
188220 uint64_t header = llvm::support::endian::byte_swap (
189221 uint64_t (size), llvm::support::endianness::little);
190- writtenSize = write (&header, sizeof (header));
222+ writtenSize = Process-> write (&header, sizeof (header));
191223 if (writtenSize != sizeof (header)) {
224+ setStale ();
192225 return llvm::createStringError (llvm::inconvertibleErrorCode (),
193226 " failed to write plugin message header" );
194227 }
195228
196229 // Write message.
197- writtenSize = write (data, size);
230+ writtenSize = Process-> write (data, size);
198231 if (writtenSize != ssize_t (size)) {
232+ setStale ();
199233 return llvm::createStringError (llvm::inconvertibleErrorCode (),
200234 " failed to write plugin message data" );
201235 }
@@ -208,9 +242,10 @@ llvm::Expected<std::string> LoadedExecutablePlugin::waitForNextMessage() const {
208242
209243 // Read header (message size).
210244 uint64_t header;
211- readSize = read (&header, sizeof (header));
245+ readSize = Process-> read (&header, sizeof (header));
212246
213247 if (readSize != sizeof (header)) {
248+ setStale ();
214249 return llvm::createStringError (llvm::inconvertibleErrorCode (),
215250 " failed to read plugin message header" );
216251 }
@@ -224,8 +259,9 @@ llvm::Expected<std::string> LoadedExecutablePlugin::waitForNextMessage() const {
224259 auto sizeToRead = size;
225260 while (sizeToRead > 0 ) {
226261 char buffer[4096 ];
227- readSize = read (buffer, std::min (sizeof (buffer), sizeToRead));
262+ readSize = Process-> read (buffer, std::min (sizeof (buffer), sizeToRead));
228263 if (readSize == 0 ) {
264+ setStale ();
229265 return llvm::createStringError (llvm::inconvertibleErrorCode (),
230266 " failed to read plugin message data" );
231267 }
0 commit comments