@@ -27,32 +27,13 @@ static struct command_result *plugin_dynamic_list_plugins(struct command *cmd,
27
27
json_add_string (response , "name" , p -> cmd );
28
28
json_add_bool (response , "active" ,
29
29
p -> plugin_state == INIT_COMPLETE );
30
+ json_add_u32 (response , "state" , p -> plugin_state );
30
31
json_object_end (response );
31
32
}
32
33
json_array_end (response );
33
34
return command_success (cmd , response );
34
35
}
35
36
36
- /* Mutual recursion. */
37
- static void plugin_dynamic_crash (struct plugin * plugin , struct dynamic_plugin * dp );
38
-
39
- /**
40
- * Returned by all subcommands on error.
41
- */
42
- static struct command_result *
43
- plugin_dynamic_error (struct dynamic_plugin * dp , const char * error )
44
- {
45
- if (dp -> plugin )
46
- plugin_kill (dp -> plugin , "%s" , error );
47
- else
48
- log_info (dp -> cmd -> ld -> log , "%s" , error );
49
-
50
- tal_del_destructor2 (dp -> plugin , plugin_dynamic_crash , dp );
51
- return command_fail (dp -> cmd , JSONRPC2_INVALID_PARAMS ,
52
- "%s: %s" , dp -> plugin ? dp -> plugin -> cmd : "unknown plugin" ,
53
- error );
54
- }
55
-
56
37
struct command_result * plugin_cmd_killed (struct command * cmd ,
57
38
struct plugin * plugin , const char * msg )
58
39
{
@@ -71,143 +52,27 @@ struct command_result *plugin_cmd_all_complete(struct plugins *plugins,
71
52
return plugin_dynamic_list_plugins (cmd , plugins );
72
53
}
73
54
74
- static void plugin_dynamic_timeout (struct dynamic_plugin * dp )
75
- {
76
- plugin_dynamic_error (dp , "Timed out while waiting for plugin response" );
77
- }
78
-
79
- static void plugin_dynamic_crash (struct plugin * p , struct dynamic_plugin * dp )
80
- {
81
- plugin_dynamic_error (dp , "Plugin exited before completing handshake." );
82
- }
83
-
84
- static void plugin_dynamic_config_callback (const char * buffer ,
85
- const jsmntok_t * toks ,
86
- const jsmntok_t * idtok ,
87
- struct dynamic_plugin * dp )
88
- {
89
- struct plugin * p ;
90
-
91
- dp -> plugin -> plugin_state = INIT_COMPLETE ;
92
- /* Reset the timer only now so that we are either configured, or
93
- * killed. */
94
- tal_free (dp -> plugin -> timeout_timer );
95
- tal_del_destructor2 (dp -> plugin , plugin_dynamic_crash , dp );
96
-
97
- list_for_each (& dp -> plugin -> plugins -> plugins , p , list ) {
98
- if (p -> plugin_state != INIT_COMPLETE )
99
- return ;
100
- }
101
-
102
- /* No plugin unconfigured left, return the plugin list */
103
- was_pending (plugin_dynamic_list_plugins (dp -> cmd , dp -> plugin -> plugins ));
104
- }
105
-
106
- /**
107
- * Send the init message to the plugin. We don't care about its response,
108
- * but it's considered the last part of the handshake : once it responds
109
- * it is considered configured.
110
- */
111
- static void plugin_dynamic_config (struct dynamic_plugin * dp )
112
- {
113
- struct jsonrpc_request * req ;
114
-
115
- req = jsonrpc_request_start (dp -> plugin , "init" , dp -> plugin -> log ,
116
- plugin_dynamic_config_callback , dp );
117
- plugin_populate_init_request (dp -> plugin , req );
118
- jsonrpc_request_end (req );
119
- dp -> plugin -> plugin_state = AWAITING_INIT_RESPONSE ;
120
- plugin_request_send (dp -> plugin , req );
121
- }
122
-
123
- static void plugin_dynamic_manifest_callback (const char * buffer ,
124
- const jsmntok_t * toks ,
125
- const jsmntok_t * idtok ,
126
- struct dynamic_plugin * dp )
127
- {
128
- if (!plugin_parse_getmanifest_response (buffer , toks , idtok , dp -> plugin ))
129
- return was_pending (plugin_dynamic_error (dp , "Gave a bad response to getmanifest" ));
130
-
131
- if (!dp -> plugin -> dynamic )
132
- return was_pending (plugin_dynamic_error (dp , "Not a dynamic plugin" ));
133
-
134
- /* We got the manifest, now send the init message */
135
- dp -> plugin -> plugin_state = NEEDS_INIT ;
136
- plugin_dynamic_config (dp );
137
- }
138
-
139
- /**
140
- * This starts a plugin : spawns the process, connect its stdout and stdin,
141
- * then sends it a getmanifest request.
142
- */
143
- static struct command_result * plugin_start (struct dynamic_plugin * dp )
144
- {
145
- int stdin , stdout ;
146
- mode_t prev_mask ;
147
- char * * p_cmd ;
148
- struct jsonrpc_request * req ;
149
- struct plugin * p = dp -> plugin ;
150
-
151
- p -> dynamic = false;
152
- p_cmd = tal_arrz (NULL , char * , 2 );
153
- p_cmd [0 ] = p -> cmd ;
154
- /* In case the plugin create files, this is a better default. */
155
- prev_mask = umask (dp -> cmd -> ld -> initial_umask );
156
- p -> pid = pipecmdarr (& stdin , & stdout , & pipecmd_preserve , p_cmd );
157
- umask (prev_mask );
158
- if (p -> pid == -1 )
159
- return plugin_dynamic_error (dp , "Error running command" );
160
- else
161
- log_debug (dp -> cmd -> ld -> plugins -> log , "started(%u) %s" , p -> pid , p -> cmd );
162
- tal_free (p_cmd );
163
- p -> buffer = tal_arr (p , char , 64 );
164
- p -> stop = false;
165
- /* Give the plugin 20 seconds to respond to `getmanifest`, so we don't hang
166
- * too long on the RPC caller. */
167
- p -> timeout_timer = new_reltimer (dp -> cmd -> ld -> timers , dp ,
168
- time_from_sec ((20 )),
169
- plugin_dynamic_timeout , dp );
170
-
171
- /* Besides the timeout we could also have the plugin crash before
172
- * completing the handshake. In that case we'll get notified and we
173
- * can clean up the `struct dynamic_plugin` and return an appropriate
174
- * error.
175
- *
176
- * The destructor is deregistered in the following places:
177
- *
178
- * - plugin_dynamic_error in case of a timeout or a crash
179
- * - plugin_dynamic_config_callback if the handshake completes
180
- */
181
- tal_add_destructor2 (p , plugin_dynamic_crash , dp );
182
-
183
- /* Create two connections, one read-only on top of the plugin's stdin, and one
184
- * write-only on its stdout. */
185
- io_new_conn (p , stdout , plugin_stdout_conn_init , p );
186
- io_new_conn (p , stdin , plugin_stdin_conn_init , p );
187
- req = jsonrpc_request_start (p , "getmanifest" , p -> log ,
188
- plugin_dynamic_manifest_callback , dp );
189
- jsonrpc_request_end (req );
190
- plugin_request_send (p , req );
191
- p -> plugin_state = AWAITING_GETMANIFEST_RESPONSE ;
192
- return command_still_pending (dp -> cmd );
193
- }
194
-
195
55
/**
196
56
* Called when trying to start a plugin through RPC, it starts the plugin and
197
57
* will give a result 20 seconds later at the most.
198
58
*/
199
59
static struct command_result *
200
60
plugin_dynamic_start (struct command * cmd , const char * plugin_path )
201
61
{
202
- struct dynamic_plugin * dp ;
62
+ struct plugin * p = plugin_register ( cmd -> ld -> plugins , plugin_path , cmd ) ;
203
63
204
- dp = tal (cmd , struct dynamic_plugin );
205
- dp -> cmd = cmd ;
206
- dp -> plugin = plugin_register (cmd -> ld -> plugins , plugin_path , NULL );
207
- if (!dp -> plugin )
208
- return plugin_dynamic_error (dp , "Is already registered" );
64
+ if (!p )
65
+ return command_fail (cmd , JSONRPC2_INVALID_PARAMS ,
66
+ "%s: already registered" ,
67
+ plugin_path );
209
68
210
- return plugin_start (dp );
69
+ /* This will come back via plugin_cmd_killed or plugin_cmd_succeeded */
70
+ if (!plugin_send_getmanifest (p ))
71
+ return command_fail (cmd , PLUGIN_ERROR ,
72
+ "%s: failed to open: %s" ,
73
+ plugin_path , strerror (errno ));
74
+
75
+ return command_still_pending (cmd );
211
76
}
212
77
213
78
/**
@@ -218,38 +83,23 @@ static struct command_result *
218
83
plugin_dynamic_startdir (struct command * cmd , const char * dir_path )
219
84
{
220
85
const char * err ;
221
- struct plugin * p ;
222
- /* If the directory is empty */
223
- bool found ;
86
+ struct command_result * res ;
224
87
225
88
err = add_plugin_dir (cmd -> ld -> plugins , dir_path , false);
226
89
if (err )
227
90
return command_fail (cmd , JSONRPC2_INVALID_PARAMS , "%s" , err );
228
91
229
- found = false;
230
- list_for_each (& cmd -> ld -> plugins -> plugins , p , list ) {
231
- if (p -> plugin_state == UNCONFIGURED ) {
232
- found = true;
233
- struct dynamic_plugin * dp = tal (cmd , struct dynamic_plugin );
234
- dp -> plugin = p ;
235
- dp -> cmd = cmd ;
236
- plugin_start (dp );
237
- }
238
- }
239
- if (!found )
240
- plugin_dynamic_list_plugins (cmd , cmd -> ld -> plugins );
92
+ /* If none added, this calls plugin_cmd_all_complete immediately */
93
+ res = plugin_register_all_complete (cmd -> ld , cmd );
94
+ if (res )
95
+ return res ;
241
96
97
+ plugins_send_getmanifest (cmd -> ld -> plugins );
242
98
return command_still_pending (cmd );
243
99
}
244
100
245
101
static void clear_plugin (struct plugin * p , const char * name )
246
102
{
247
- struct plugin_opt * opt ;
248
-
249
- list_for_each (& p -> plugin_opts , opt , list )
250
- if (!opt_unregister (opt -> name ))
251
- fatal ("Could not unregister %s from plugin %s" ,
252
- opt -> name , name );
253
103
plugin_kill (p , "%s stopped by lightningd via RPC" , name );
254
104
tal_free (p );
255
105
}
@@ -290,25 +140,16 @@ plugin_dynamic_stop(struct command *cmd, const char *plugin_name)
290
140
static struct command_result *
291
141
plugin_dynamic_rescan_plugins (struct command * cmd )
292
142
{
293
- bool found ;
294
- struct plugin * p ;
143
+ struct command_result * res ;
295
144
296
145
/* This will not fail on "already registered" error. */
297
146
plugins_add_default_dir (cmd -> ld -> plugins );
298
147
299
- found = false;
300
- list_for_each (& cmd -> ld -> plugins -> plugins , p , list ) {
301
- if (p -> plugin_state == UNCONFIGURED ) {
302
- struct dynamic_plugin * dp = tal (cmd , struct dynamic_plugin );
303
- dp -> plugin = p ;
304
- dp -> cmd = cmd ;
305
- plugin_start (dp );
306
- found = true;
307
- }
308
- }
148
+ /* If none added, this calls plugin_cmd_all_complete immediately */
149
+ res = plugin_register_all_complete (cmd -> ld , cmd );
150
+ if (res )
151
+ return res ;
309
152
310
- if (!found )
311
- return plugin_dynamic_list_plugins (cmd , cmd -> ld -> plugins );
312
153
return command_still_pending (cmd );
313
154
}
314
155
0 commit comments