38
38
#include < io.h>
39
39
#endif
40
40
41
- extern " C" const void *swift_ASTGen_getCompilerPluginCapability (void *handle);
42
- extern " C" void swift_ASTGen_destroyCompilerPluginCapability (void *value);
43
-
44
41
using namespace swift ;
45
42
46
43
llvm::Expected<void *> PluginRegistry::loadLibraryPlugin (StringRef path) {
@@ -74,14 +71,14 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
74
71
}
75
72
76
73
// See if the plugin is already loaded.
77
- auto &plugin = LoadedPluginExecutables[path];
78
- if (plugin ) {
74
+ auto &storage = LoadedPluginExecutables[path];
75
+ if (storage ) {
79
76
// 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 ();
82
79
83
80
// The plugin is updated. Close the previously opened plugin.
84
- plugin = nullptr ;
81
+ storage = nullptr ;
85
82
}
86
83
87
84
if (!llvm::sys::fs::exists (stat)) {
@@ -94,8 +91,35 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
94
91
" not executable" );
95
92
}
96
93
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
+
97
121
// Create command line arguments.
98
- SmallVector<StringRef, 4 > command{path };
122
+ SmallVector<StringRef, 4 > command{ExecutablePath };
99
123
100
124
// Apply sandboxing.
101
125
llvm::BumpPtrAllocator Allocator;
@@ -107,29 +131,36 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
107
131
return llvm::errorCodeToError (childInfo.getError ());
108
132
}
109
133
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
+ }
113
142
114
- return plugin. get ();
143
+ return llvm::Error::success ();
115
144
}
116
145
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),
122
150
outputFileDescriptor(outputFileDescriptor) {}
123
151
124
- LoadedExecutablePlugin::~LoadedExecutablePlugin () {
152
+ LoadedExecutablePlugin::PluginProcess::~PluginProcess () {
125
153
close (inputFileDescriptor);
126
154
close (outputFileDescriptor);
155
+ }
127
156
157
+ LoadedExecutablePlugin::~LoadedExecutablePlugin () {
128
158
// Let ASTGen to cleanup things.
129
159
this ->cleanup ();
130
160
}
131
161
132
- ssize_t LoadedExecutablePlugin::read (void *buf, size_t nbyte) const {
162
+ ssize_t LoadedExecutablePlugin::PluginProcess::read (void *buf,
163
+ size_t nbyte) const {
133
164
ssize_t bytesToRead = nbyte;
134
165
void *ptr = buf;
135
166
@@ -154,7 +185,8 @@ ssize_t LoadedExecutablePlugin::read(void *buf, size_t nbyte) const {
154
185
return nbyte - bytesToRead;
155
186
}
156
187
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 {
158
190
ssize_t bytesToWrite = nbyte;
159
191
const void *ptr = buf;
160
192
@@ -187,15 +219,17 @@ llvm::Error LoadedExecutablePlugin::sendMessage(llvm::StringRef message) const {
187
219
// Write header (message size).
188
220
uint64_t header = llvm::support::endian::byte_swap (
189
221
uint64_t (size), llvm::support::endianness::little);
190
- writtenSize = write (&header, sizeof (header));
222
+ writtenSize = Process-> write (&header, sizeof (header));
191
223
if (writtenSize != sizeof (header)) {
224
+ setStale ();
192
225
return llvm::createStringError (llvm::inconvertibleErrorCode (),
193
226
" failed to write plugin message header" );
194
227
}
195
228
196
229
// Write message.
197
- writtenSize = write (data, size);
230
+ writtenSize = Process-> write (data, size);
198
231
if (writtenSize != ssize_t (size)) {
232
+ setStale ();
199
233
return llvm::createStringError (llvm::inconvertibleErrorCode (),
200
234
" failed to write plugin message data" );
201
235
}
@@ -208,9 +242,10 @@ llvm::Expected<std::string> LoadedExecutablePlugin::waitForNextMessage() const {
208
242
209
243
// Read header (message size).
210
244
uint64_t header;
211
- readSize = read (&header, sizeof (header));
245
+ readSize = Process-> read (&header, sizeof (header));
212
246
213
247
if (readSize != sizeof (header)) {
248
+ setStale ();
214
249
return llvm::createStringError (llvm::inconvertibleErrorCode (),
215
250
" failed to read plugin message header" );
216
251
}
@@ -224,8 +259,9 @@ llvm::Expected<std::string> LoadedExecutablePlugin::waitForNextMessage() const {
224
259
auto sizeToRead = size;
225
260
while (sizeToRead > 0 ) {
226
261
char buffer[4096 ];
227
- readSize = read (buffer, std::min (sizeof (buffer), sizeToRead));
262
+ readSize = Process-> read (buffer, std::min (sizeof (buffer), sizeToRead));
228
263
if (readSize == 0 ) {
264
+ setStale ();
229
265
return llvm::createStringError (llvm::inconvertibleErrorCode (),
230
266
" failed to read plugin message data" );
231
267
}
0 commit comments