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) {
@@ -94,8 +91,35 @@ PluginRegistry::loadExecutablePlugin(StringRef path) {
94
91
" not executable" );
95
92
}
96
93
94
+ 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
+ plugin.reset ();
101
+ return std::move (error);
102
+ }
103
+
104
+ return plugin.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 ));
113
137
114
- return plugin.get ();
138
+ // Call "on reconnect" callbacks.
139
+ for (auto *callback : onReconnect) {
140
+ (*callback)();
141
+ }
142
+
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
@@ -179,6 +211,7 @@ ssize_t LoadedExecutablePlugin::write(const void *buf, size_t nbyte) const {
179
211
}
180
212
181
213
llvm::Error LoadedExecutablePlugin::sendMessage (llvm::StringRef message) const {
214
+ assert (isAlive ());
182
215
ssize_t writtenSize = 0 ;
183
216
184
217
const char *data = message.data ();
@@ -187,15 +220,17 @@ llvm::Error LoadedExecutablePlugin::sendMessage(llvm::StringRef message) const {
187
220
// Write header (message size).
188
221
uint64_t header = llvm::support::endian::byte_swap (
189
222
uint64_t (size), llvm::support::endianness::little);
190
- writtenSize = write (&header, sizeof (header));
223
+ writtenSize = Process-> write (&header, sizeof (header));
191
224
if (writtenSize != sizeof (header)) {
225
+ setStale ();
192
226
return llvm::createStringError (llvm::inconvertibleErrorCode (),
193
227
" failed to write plugin message header" );
194
228
}
195
229
196
230
// Write message.
197
- writtenSize = write (data, size);
231
+ writtenSize = Process-> write (data, size);
198
232
if (writtenSize != ssize_t (size)) {
233
+ setStale ();
199
234
return llvm::createStringError (llvm::inconvertibleErrorCode (),
200
235
" failed to write plugin message data" );
201
236
}
@@ -204,13 +239,15 @@ llvm::Error LoadedExecutablePlugin::sendMessage(llvm::StringRef message) const {
204
239
}
205
240
206
241
llvm::Expected<std::string> LoadedExecutablePlugin::waitForNextMessage () const {
242
+ assert (isAlive ());
207
243
ssize_t readSize = 0 ;
208
244
209
245
// Read header (message size).
210
246
uint64_t header;
211
- readSize = read (&header, sizeof (header));
247
+ readSize = Process-> read (&header, sizeof (header));
212
248
213
249
if (readSize != sizeof (header)) {
250
+ setStale ();
214
251
return llvm::createStringError (llvm::inconvertibleErrorCode (),
215
252
" failed to read plugin message header" );
216
253
}
@@ -224,8 +261,9 @@ llvm::Expected<std::string> LoadedExecutablePlugin::waitForNextMessage() const {
224
261
auto sizeToRead = size;
225
262
while (sizeToRead > 0 ) {
226
263
char buffer[4096 ];
227
- readSize = read (buffer, std::min (sizeof (buffer), sizeToRead));
264
+ readSize = Process-> read (buffer, std::min (sizeof (buffer), sizeToRead));
228
265
if (readSize == 0 ) {
266
+ setStale ();
229
267
return llvm::createStringError (llvm::inconvertibleErrorCode (),
230
268
" failed to read plugin message data" );
231
269
}
0 commit comments