24
24
Java_net_dot_MonoRunner_setEnv (JNIEnv * env , jobject thiz , jstring j_key , jstring j_value );
25
25
26
26
int
27
- Java_net_dot_MonoRunner_initRuntime (JNIEnv * env , jobject thiz , jstring j_files_dir , jstring j_cache_dir , jstring j_testresults_dir , jstring j_entryPointLibName , jobjectArray j_args , long current_local_time );
27
+ Java_net_dot_MonoRunner_initRuntime (JNIEnv * env , jobject thiz , jstring j_files_dir , jstring j_entryPointLibName , long current_local_time );
28
+
29
+ int
30
+ Java_net_dot_MonoRunner_execEntryPoint (JNIEnv * env , jobject thiz , jstring j_entryPointLibName , jobjectArray j_args );
31
+
32
+ void
33
+ Java_net_dot_MonoRunner_freeNativeResources (JNIEnv * env , jobject thiz );
28
34
29
35
/********* implementation *********/
30
36
31
- static char * bundle_path ;
32
- static char * executable ;
37
+ static const char * g_bundle_path = NULL ;
38
+ static const char * g_executable_path = NULL ;
39
+ static unsigned int g_coreclr_domainId = 0 ;
40
+ static void * g_coreclr_handle = NULL ;
41
+
33
42
34
43
#define LOG_INFO (fmt , ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__)
35
44
#define LOG_ERROR (fmt , ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__)
@@ -54,21 +63,11 @@ strncpy_str (JNIEnv *env, char *buff, jstring str, int nbuff)
54
63
jboolean isCopy = 0 ;
55
64
const char * copy_buff = (* env )-> GetStringUTFChars (env , str , & isCopy );
56
65
strncpy (buff , copy_buff , nbuff );
66
+ buff [nbuff - 1 ] = '\0' ; // ensure '\0' terminated
57
67
if (isCopy )
58
68
(* env )-> ReleaseStringUTFChars (env , str , copy_buff );
59
69
}
60
70
61
- void
62
- Java_net_dot_MonoRunner_setEnv (JNIEnv * env , jobject thiz , jstring j_key , jstring j_value )
63
- {
64
- LOG_INFO ("Java_net_dot_MonoRunner_setEnv:" );
65
- const char * key = (* env )-> GetStringUTFChars (env , j_key , 0 );
66
- const char * val = (* env )-> GetStringUTFChars (env , j_value , 0 );
67
- setenv (key , val , true);
68
- (* env )-> ReleaseStringUTFChars (env , j_key , key );
69
- (* env )-> ReleaseStringUTFChars (env , j_value , val );
70
- }
71
-
72
71
/*
73
72
* Get the list of trusted assemblies from a specified @dir_path.
74
73
* The path is searched for .dll files which when found are concatenated
@@ -130,11 +129,67 @@ get_tpas_from_path(const char* dir_path, const char** tpas)
130
129
}
131
130
132
131
static int
133
- mono_droid_runtime_init (const char * executable , int managed_argc , char * managed_argv [], int local_date_time_offset )
132
+ bundle_executable_path (const char * executable , const char * bundle_path , const char * * executable_path )
134
133
{
135
- LOG_INFO ("mono_droid_runtime_init called with executable: %s" , executable );
134
+ size_t executable_path_len = strlen (bundle_path ) + strlen (executable ) + 1 ; // +1 for '/'
135
+ char * temp_path = (char * )malloc (sizeof (char ) * (executable_path_len + 1 )); // +1 for '\0'
136
+ if (temp_path == NULL )
137
+ {
138
+ return -1 ;
139
+ }
136
140
137
- chdir (bundle_path );
141
+ size_t res = snprintf (temp_path , (executable_path_len + 1 ), "%s/%s" , bundle_path , executable );
142
+ if (res < 0 || res != executable_path_len )
143
+ {
144
+ return -1 ;
145
+ }
146
+ * executable_path = temp_path ;
147
+ return executable_path_len ;
148
+ }
149
+
150
+ static void
151
+ free_resources ()
152
+ {
153
+ if (g_bundle_path )
154
+ {
155
+ free (g_bundle_path );
156
+ g_bundle_path = NULL ;
157
+ }
158
+ if (g_executable_path )
159
+ {
160
+ free (g_executable_path );
161
+ g_executable_path = NULL ;
162
+ }
163
+ if (g_coreclr_handle )
164
+ {
165
+ // Clean up some coreclr resources. This doesn't make coreclr unloadable.
166
+ coreclr_shutdown (g_coreclr_handle , g_coreclr_domainId );
167
+ g_coreclr_handle = NULL ;
168
+ }
169
+ }
170
+
171
+ static int
172
+ mono_droid_execute_assembly (const char * executable_path , void * coreclr_handle , unsigned int coreclr_domainId , int managed_argc , const char * * managed_argv )
173
+ {
174
+ unsigned int rv ;
175
+ LOG_INFO ("Calling coreclr_execute_assembly" );
176
+ coreclr_execute_assembly (coreclr_handle , coreclr_domainId , managed_argc , managed_argv , executable_path , & rv );
177
+ LOG_INFO ("Exit code: %u." , rv );
178
+ return rv ;
179
+ }
180
+
181
+ static int
182
+ mono_droid_runtime_init (const char * executable )
183
+ {
184
+ LOG_INFO ("mono_droid_runtime_init (CoreCLR) called with executable: %s" , executable );
185
+
186
+ if (bundle_executable_path (executable , g_bundle_path , & g_executable_path ) < 0 )
187
+ {
188
+ LOG_ERROR ("Failed to resolve full path for: %s" , executable );
189
+ return -1 ;
190
+ }
191
+
192
+ chdir (g_bundle_path );
138
193
139
194
// TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES
140
195
@@ -145,78 +200,99 @@ mono_droid_runtime_init (const char* executable, int managed_argc, char* managed
145
200
146
201
const char * appctx_values [3 ];
147
202
appctx_values [0 ] = ANDROID_RUNTIME_IDENTIFIER ;
148
- appctx_values [1 ] = bundle_path ;
149
- size_t tpas_len = get_tpas_from_path (bundle_path , & appctx_values [2 ]);
203
+ appctx_values [1 ] = g_bundle_path ;
204
+ size_t tpas_len = get_tpas_from_path (g_bundle_path , & appctx_values [2 ]);
150
205
if (tpas_len < 1 )
151
206
{
152
- LOG_ERROR ("Failed to get trusted assemblies from path: %s" , bundle_path );
207
+ LOG_ERROR ("Failed to get trusted assemblies from path: %s" , g_bundle_path );
153
208
return -1 ;
154
209
}
155
210
156
- size_t executable_path_len = strlen (bundle_path ) + strlen (executable ) + 2 ; // +2 for '/' and '\0'
157
- char * executable_path = (char * )malloc (executable_path_len );
158
- size_t res = sprintf (executable_path , "%s/%s" , bundle_path , executable );
159
- if (res != executable_path_len - 1 )
160
- {
161
- LOG_ERROR ("Failed to resolve full path for: %s" , executable );
162
- return -1 ;
163
- }
164
- executable_path [res ] = '\0' ;
165
-
166
- unsigned int coreclr_domainId = 0 ;
167
- void * coreclr_handle = NULL ;
168
-
169
211
LOG_INFO ("Calling coreclr_initialize" );
170
212
int rv = coreclr_initialize (
171
- executable_path ,
213
+ g_executable_path ,
172
214
executable ,
173
215
3 ,
174
216
appctx_keys ,
175
217
appctx_values ,
176
- & coreclr_handle ,
177
- & coreclr_domainId
218
+ & g_coreclr_handle ,
219
+ & g_coreclr_domainId
178
220
);
179
221
LOG_INFO ("coreclr_initialize returned %d" , rv );
222
+ return rv ;
223
+ }
180
224
181
- LOG_INFO ("Calling coreclr_execute_assembly" );
182
- coreclr_execute_assembly (coreclr_handle , coreclr_domainId , managed_argc , managed_argv , executable_path , & rv );
225
+ void
226
+ Java_net_dot_MonoRunner_setEnv (JNIEnv * env , jobject thiz , jstring j_key , jstring j_value )
227
+ {
228
+ LOG_INFO ("Java_net_dot_MonoRunner_setEnv:" );
229
+ assert (g_coreclr_handle == NULL ); // setenv should be only called before the runtime is initialized
183
230
184
- LOG_INFO ("Exit code: %d." , rv );
185
- return rv ;
231
+ const char * key = (* env )-> GetStringUTFChars (env , j_key , 0 );
232
+ const char * val = (* env )-> GetStringUTFChars (env , j_value , 0 );
233
+
234
+ LOG_INFO ("Setting env: %s=%s" , key , val );
235
+ setenv (key , val , true);
236
+ (* env )-> ReleaseStringUTFChars (env , j_key , key );
237
+ (* env )-> ReleaseStringUTFChars (env , j_value , val );
186
238
}
187
239
188
240
int
189
- Java_net_dot_MonoRunner_initRuntime (JNIEnv * env , jobject thiz , jstring j_files_dir , jstring j_cache_dir , jstring j_testresults_dir , jstring j_entryPointLibName , jobjectArray j_args , long current_local_time )
241
+ Java_net_dot_MonoRunner_initRuntime (JNIEnv * env , jobject thiz , jstring j_files_dir , jstring j_entryPointLibName , long current_local_time )
190
242
{
191
- LOG_INFO ("Java_net_dot_MonoRunner_initRuntime:" );
243
+ LOG_INFO ("Java_net_dot_MonoRunner_initRuntime (CoreCLR) :" );
192
244
char file_dir [2048 ];
193
- char cache_dir [2048 ];
194
- char testresults_dir [2048 ];
195
245
char entryPointLibName [2048 ];
196
246
strncpy_str (env , file_dir , j_files_dir , sizeof (file_dir ));
197
- strncpy_str (env , cache_dir , j_cache_dir , sizeof (cache_dir ));
198
- strncpy_str (env , testresults_dir , j_testresults_dir , sizeof (testresults_dir ));
199
247
strncpy_str (env , entryPointLibName , j_entryPointLibName , sizeof (entryPointLibName ));
200
248
201
- bundle_path = file_dir ;
202
- executable = entryPointLibName ;
249
+ size_t file_dir_len = strlen (file_dir );
250
+ char * bundle_path_tmp = (char * )malloc (sizeof (char ) * (file_dir_len + 1 )); // +1 for '\0'
251
+ if (bundle_path_tmp == NULL )
252
+ {
253
+ LOG_ERROR ("Failed to allocate memory for bundle_path" );
254
+ return -1 ;
255
+ }
256
+ strncpy (bundle_path_tmp , file_dir , file_dir_len + 1 );
257
+ g_bundle_path = bundle_path_tmp ;
258
+
259
+ return mono_droid_runtime_init (entryPointLibName );
260
+ }
261
+
262
+ int
263
+ Java_net_dot_MonoRunner_execEntryPoint (JNIEnv * env , jobject thiz , jstring j_entryPointLibName , jobjectArray j_args )
264
+ {
265
+ LOG_INFO ("Java_net_dot_MonoRunner_execEntryPoint (CoreCLR):" );
266
+
267
+ if ((g_bundle_path == NULL ) || (g_executable_path == NULL ))
268
+ {
269
+ LOG_ERROR ("Bundle path or executable path not set" );
270
+ return -1 ;
271
+ }
203
272
204
- setenv ("HOME" , bundle_path , true);
205
- setenv ("TMPDIR" , cache_dir , true);
206
- setenv ("TEST_RESULTS_DIR" , testresults_dir , true);
273
+ if ((g_coreclr_handle == NULL ) || (g_coreclr_domainId == 0 ))
274
+ {
275
+ LOG_ERROR ("CoreCLR not initialized" );
276
+ return -1 ;
277
+ }
207
278
208
- int args_len = (* env )-> GetArrayLength (env , j_args );
279
+ int args_len = (* env )-> GetArrayLength (env , j_args );
209
280
int managed_argc = args_len + 1 ;
210
- char * * managed_argv = (char * * )malloc (managed_argc * sizeof (char * ));
281
+ const char * * managed_argv = (const char * * )malloc (managed_argc * sizeof (char * ));
282
+ if (managed_argv == NULL )
283
+ {
284
+ LOG_ERROR ("Failed to allocate memory for managed_argv" );
285
+ return -1 ;
286
+ }
211
287
212
- managed_argv [0 ] = bundle_path ;
288
+ managed_argv [0 ] = g_bundle_path ;
213
289
for (int i = 0 ; i < args_len ; ++ i )
214
290
{
215
291
jstring j_arg = (* env )-> GetObjectArrayElement (env , j_args , i );
216
292
managed_argv [i + 1 ] = (char * )((* env )-> GetStringUTFChars (env , j_arg , NULL ));
217
293
}
218
294
219
- int res = mono_droid_runtime_init ( executable , managed_argc , managed_argv , current_local_time );
295
+ int rv = mono_droid_execute_assembly ( g_executable_path , g_coreclr_handle , g_coreclr_domainId , managed_argc , managed_argv );
220
296
221
297
for (int i = 0 ; i < args_len ; ++ i )
222
298
{
@@ -225,6 +301,12 @@ Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_
225
301
}
226
302
227
303
free (managed_argv );
228
- return res ;
304
+ return rv ;
229
305
}
230
306
307
+ void
308
+ Java_net_dot_MonoRunner_freeNativeResources (JNIEnv * env , jobject thiz )
309
+ {
310
+ LOG_INFO ("Java_net_dot_MonoRunner_freeNativeResources (CoreCLR):" );
311
+ free_resources ();
312
+ }
0 commit comments