xref: /unit/src/nxt_java.c (revision 1980:43553aa72111)
1977Smax.romanov@gmail.com 
2977Smax.romanov@gmail.com /*
3977Smax.romanov@gmail.com  * Copyright (C) NGINX, Inc.
4977Smax.romanov@gmail.com  */
5977Smax.romanov@gmail.com 
6977Smax.romanov@gmail.com 
7977Smax.romanov@gmail.com #include <jni.h>
8977Smax.romanov@gmail.com 
9977Smax.romanov@gmail.com #include <nxt_main.h>
10977Smax.romanov@gmail.com #include <nxt_runtime.h>
11977Smax.romanov@gmail.com #include <nxt_router.h>
12977Smax.romanov@gmail.com #include <nxt_unit.h>
13977Smax.romanov@gmail.com #include <nxt_unit_field.h>
14977Smax.romanov@gmail.com #include <nxt_unit_request.h>
15977Smax.romanov@gmail.com #include <nxt_unit_response.h>
161157Smax.romanov@nginx.com #include <nxt_unit_websocket.h>
17977Smax.romanov@gmail.com 
18977Smax.romanov@gmail.com #include <java/nxt_jni.h>
19977Smax.romanov@gmail.com 
20977Smax.romanov@gmail.com #include "java/nxt_jni_Thread.h"
21977Smax.romanov@gmail.com #include "java/nxt_jni_Context.h"
22977Smax.romanov@gmail.com #include "java/nxt_jni_Request.h"
23977Smax.romanov@gmail.com #include "java/nxt_jni_Response.h"
24977Smax.romanov@gmail.com #include "java/nxt_jni_InputStream.h"
25977Smax.romanov@gmail.com #include "java/nxt_jni_OutputStream.h"
26977Smax.romanov@gmail.com #include "java/nxt_jni_URLClassLoader.h"
27977Smax.romanov@gmail.com 
28977Smax.romanov@gmail.com #include "nxt_jars.h"
291532St.nateldemoura@f5.com 
301532St.nateldemoura@f5.com #include NXT_JAVA_MOUNTS_H
31977Smax.romanov@gmail.com 
321488St.nateldemoura@f5.com static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
33977Smax.romanov@gmail.com     nxt_common_app_conf_t *conf);
341488St.nateldemoura@f5.com static nxt_int_t nxt_java_start(nxt_task_t *task,
351488St.nateldemoura@f5.com     nxt_process_data_t *data);
36977Smax.romanov@gmail.com static void nxt_java_request_handler(nxt_unit_request_info_t *req);
371157Smax.romanov@nginx.com static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws);
381157Smax.romanov@nginx.com static void nxt_java_close_handler(nxt_unit_request_info_t *req);
391684Smax.romanov@nginx.com static int nxt_java_ready_handler(nxt_unit_ctx_t *ctx);
401684Smax.romanov@nginx.com static void *nxt_java_thread_func(void *main_ctx);
411684Smax.romanov@nginx.com static int nxt_java_init_threads(nxt_java_app_conf_t *c);
421684Smax.romanov@nginx.com static void nxt_java_join_threads(nxt_unit_ctx_t *ctx,
431684Smax.romanov@nginx.com     nxt_java_app_conf_t *c);
44977Smax.romanov@gmail.com 
45977Smax.romanov@gmail.com static uint32_t  compat[] = {
46977Smax.romanov@gmail.com     NXT_VERNUM, NXT_DEBUG,
47977Smax.romanov@gmail.com };
48977Smax.romanov@gmail.com 
49977Smax.romanov@gmail.com char  *nxt_java_modules;
50977Smax.romanov@gmail.com 
511684Smax.romanov@nginx.com static pthread_t       *nxt_java_threads;
521684Smax.romanov@nginx.com static pthread_attr_t  *nxt_java_thread_attr;
531684Smax.romanov@nginx.com 
54977Smax.romanov@gmail.com 
55977Smax.romanov@gmail.com #define NXT_STRING(x)   _NXT_STRING(x)
56977Smax.romanov@gmail.com #define _NXT_STRING(x)  #x
57977Smax.romanov@gmail.com 
58977Smax.romanov@gmail.com NXT_EXPORT nxt_app_module_t  nxt_app_module = {
59977Smax.romanov@gmail.com     sizeof(compat),
60977Smax.romanov@gmail.com     compat,
61977Smax.romanov@gmail.com     nxt_string("java"),
62977Smax.romanov@gmail.com     NXT_STRING(NXT_JAVA_VERSION),
631489St.nateldemoura@f5.com     nxt_java_mounts,
641489St.nateldemoura@f5.com     nxt_nitems(nxt_java_mounts),
651488St.nateldemoura@f5.com     nxt_java_setup,
661488St.nateldemoura@f5.com     nxt_java_start,
67977Smax.romanov@gmail.com };
68977Smax.romanov@gmail.com 
69977Smax.romanov@gmail.com typedef struct {
701684Smax.romanov@nginx.com     JavaVM               *jvm;
711684Smax.romanov@nginx.com     jobject              cl;
721684Smax.romanov@nginx.com     jobject              ctx;
731684Smax.romanov@nginx.com     nxt_java_app_conf_t  *conf;
74977Smax.romanov@gmail.com } nxt_java_data_t;
75977Smax.romanov@gmail.com 
76977Smax.romanov@gmail.com 
77977Smax.romanov@gmail.com static nxt_int_t
nxt_java_setup(nxt_task_t * task,nxt_process_t * process,nxt_common_app_conf_t * conf)781488St.nateldemoura@f5.com nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
791488St.nateldemoura@f5.com     nxt_common_app_conf_t *conf)
80977Smax.romanov@gmail.com {
811489St.nateldemoura@f5.com     char        *path, *relpath, *p, *rootfs;
821489St.nateldemoura@f5.com     size_t      jars_dir_len, rootfs_len;
83977Smax.romanov@gmail.com     const char  *unit_jars;
84977Smax.romanov@gmail.com 
851489St.nateldemoura@f5.com     rootfs = (char *) process->isolation.rootfs;
861489St.nateldemoura@f5.com     rootfs_len = 0;
871489St.nateldemoura@f5.com 
88977Smax.romanov@gmail.com     unit_jars = conf->u.java.unit_jars;
89977Smax.romanov@gmail.com     if (unit_jars == NULL) {
901489St.nateldemoura@f5.com         if (rootfs != NULL) {
911489St.nateldemoura@f5.com             unit_jars = "/";
921489St.nateldemoura@f5.com         } else {
931489St.nateldemoura@f5.com             unit_jars = NXT_JARS;
941489St.nateldemoura@f5.com         }
95977Smax.romanov@gmail.com     }
96977Smax.romanov@gmail.com 
971489St.nateldemoura@f5.com     relpath = strdup(unit_jars);
981489St.nateldemoura@f5.com     if (nxt_slow_path(relpath == NULL)) {
99977Smax.romanov@gmail.com         return NXT_ERROR;
100977Smax.romanov@gmail.com     }
101977Smax.romanov@gmail.com 
1021489St.nateldemoura@f5.com     if (rootfs != NULL) {
1031489St.nateldemoura@f5.com         jars_dir_len = strlen(unit_jars);
1041489St.nateldemoura@f5.com         rootfs_len = strlen(rootfs);
1051489St.nateldemoura@f5.com 
1061489St.nateldemoura@f5.com         path = nxt_malloc(jars_dir_len + rootfs_len + 1);
1071489St.nateldemoura@f5.com         if (nxt_slow_path(path == NULL)) {
1081489St.nateldemoura@f5.com             free(relpath);
1091489St.nateldemoura@f5.com             return NXT_ERROR;
1101489St.nateldemoura@f5.com         }
1111489St.nateldemoura@f5.com 
1121489St.nateldemoura@f5.com         p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len);
1131489St.nateldemoura@f5.com         p = nxt_cpymem(p, relpath, jars_dir_len);
1141489St.nateldemoura@f5.com         *p = '\0';
1151489St.nateldemoura@f5.com 
1161489St.nateldemoura@f5.com         free(relpath);
1171489St.nateldemoura@f5.com 
1181489St.nateldemoura@f5.com     } else {
1191489St.nateldemoura@f5.com         path = relpath;
1201489St.nateldemoura@f5.com     }
1211489St.nateldemoura@f5.com 
1221489St.nateldemoura@f5.com     nxt_java_modules = realpath(path, NULL);
1231489St.nateldemoura@f5.com     if (nxt_java_modules == NULL) {
1241489St.nateldemoura@f5.com         nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno);
1251489St.nateldemoura@f5.com         goto free;
1261489St.nateldemoura@f5.com     }
1271489St.nateldemoura@f5.com 
1281489St.nateldemoura@f5.com     if (rootfs != NULL && strlen(path) > rootfs_len) {
1291489St.nateldemoura@f5.com         nxt_java_modules = path + rootfs_len;
1301489St.nateldemoura@f5.com     }
1311489St.nateldemoura@f5.com 
1321489St.nateldemoura@f5.com     nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules);
1331489St.nateldemoura@f5.com 
134977Smax.romanov@gmail.com     return NXT_OK;
1351489St.nateldemoura@f5.com 
1361489St.nateldemoura@f5.com free:
1371489St.nateldemoura@f5.com 
1381489St.nateldemoura@f5.com     nxt_free(path);
1391489St.nateldemoura@f5.com 
1401489St.nateldemoura@f5.com     return NXT_ERROR;
141977Smax.romanov@gmail.com }
142977Smax.romanov@gmail.com 
143977Smax.romanov@gmail.com 
144977Smax.romanov@gmail.com static char **
nxt_java_module_jars(const char * jars[],int jar_count)145977Smax.romanov@gmail.com nxt_java_module_jars(const char *jars[], int jar_count)
146977Smax.romanov@gmail.com {
147977Smax.romanov@gmail.com     char        **res, *jurl;
1481489St.nateldemoura@f5.com     uint8_t     pathsep;
149977Smax.romanov@gmail.com     nxt_int_t   modules_len, jlen, i;
150977Smax.romanov@gmail.com     const char  **jar;
151977Smax.romanov@gmail.com 
152977Smax.romanov@gmail.com     res = nxt_malloc(jar_count * sizeof(char*));
153977Smax.romanov@gmail.com     if (res == NULL) {
154977Smax.romanov@gmail.com         return NULL;
155977Smax.romanov@gmail.com     }
156977Smax.romanov@gmail.com 
157977Smax.romanov@gmail.com     modules_len = nxt_strlen(nxt_java_modules);
158977Smax.romanov@gmail.com 
1591489St.nateldemoura@f5.com     pathsep = nxt_java_modules[modules_len - 1] == '/';
1601489St.nateldemoura@f5.com 
161977Smax.romanov@gmail.com     for (i = 0, jar = jars; *jar != NULL; jar++) {
1621489St.nateldemoura@f5.com         jlen = nxt_length("file:") + modules_len
1631489St.nateldemoura@f5.com                + (!pathsep ? nxt_length("/") : 0)
1641489St.nateldemoura@f5.com                + nxt_strlen(*jar) + 1;
1651489St.nateldemoura@f5.com 
166977Smax.romanov@gmail.com         jurl = nxt_malloc(jlen);
167977Smax.romanov@gmail.com         if (jurl == NULL) {
168977Smax.romanov@gmail.com             return NULL;
169977Smax.romanov@gmail.com         }
170977Smax.romanov@gmail.com 
171977Smax.romanov@gmail.com         res[i++] = jurl;
172977Smax.romanov@gmail.com 
173977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
174977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
1751489St.nateldemoura@f5.com 
1761489St.nateldemoura@f5.com         if (!pathsep) {
1771489St.nateldemoura@f5.com             *jurl++ = '/';
1781489St.nateldemoura@f5.com         }
1791489St.nateldemoura@f5.com 
180977Smax.romanov@gmail.com         jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
181977Smax.romanov@gmail.com         *jurl++ = '\0';
182977Smax.romanov@gmail.com     }
183977Smax.romanov@gmail.com 
184977Smax.romanov@gmail.com     return res;
185977Smax.romanov@gmail.com }
186977Smax.romanov@gmail.com 
187977Smax.romanov@gmail.com 
188977Smax.romanov@gmail.com static nxt_int_t
nxt_java_start(nxt_task_t * task,nxt_process_data_t * data)1891488St.nateldemoura@f5.com nxt_java_start(nxt_task_t *task, nxt_process_data_t *data)
190977Smax.romanov@gmail.com {
1911488St.nateldemoura@f5.com     jint                   rc;
1921488St.nateldemoura@f5.com     char                   *opt, *real_path;
1931488St.nateldemoura@f5.com     char                   **classpath_arr, **unit_jars, **system_jars;
1941488St.nateldemoura@f5.com     JavaVM                 *jvm;
1951488St.nateldemoura@f5.com     JNIEnv                 *env;
1961488St.nateldemoura@f5.com     jobject                cl, classpath;
1971488St.nateldemoura@f5.com     nxt_str_t              str;
1981488St.nateldemoura@f5.com     nxt_int_t              opt_len, real_path_len;
1991488St.nateldemoura@f5.com     nxt_uint_t             i, unit_jars_count, classpath_count;
2001488St.nateldemoura@f5.com     nxt_uint_t             system_jars_count;
2011488St.nateldemoura@f5.com     JavaVMOption           *jvm_opt;
2021488St.nateldemoura@f5.com     JavaVMInitArgs         jvm_args;
2031488St.nateldemoura@f5.com     nxt_unit_ctx_t         *ctx;
2041488St.nateldemoura@f5.com     nxt_unit_init_t        java_init;
2051488St.nateldemoura@f5.com     nxt_java_data_t        java_data;
2061488St.nateldemoura@f5.com     nxt_conf_value_t       *value;
2071488St.nateldemoura@f5.com     nxt_java_app_conf_t    *c;
2081488St.nateldemoura@f5.com     nxt_common_app_conf_t  *app_conf;
209977Smax.romanov@gmail.com 
210977Smax.romanov@gmail.com     //setenv("ASAN_OPTIONS", "handle_segv=0", 1);
211977Smax.romanov@gmail.com 
212977Smax.romanov@gmail.com     jvm_args.version = JNI_VERSION_1_6;
213977Smax.romanov@gmail.com     jvm_args.nOptions = 0;
214977Smax.romanov@gmail.com     jvm_args.ignoreUnrecognized = 0;
215977Smax.romanov@gmail.com 
2161488St.nateldemoura@f5.com     app_conf = data->app;
2171488St.nateldemoura@f5.com     c = &app_conf->u.java;
218977Smax.romanov@gmail.com 
219977Smax.romanov@gmail.com     if (c->options != NULL) {
220977Smax.romanov@gmail.com         jvm_args.nOptions += nxt_conf_array_elements_count(c->options);
221977Smax.romanov@gmail.com     }
222977Smax.romanov@gmail.com 
223977Smax.romanov@gmail.com     jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption));
224977Smax.romanov@gmail.com     if (jvm_opt == NULL) {
225977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate jvm_opt");
226977Smax.romanov@gmail.com         return NXT_ERROR;
227977Smax.romanov@gmail.com     }
228977Smax.romanov@gmail.com 
229977Smax.romanov@gmail.com     jvm_args.options = jvm_opt;
230977Smax.romanov@gmail.com 
231977Smax.romanov@gmail.com     unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1;
232977Smax.romanov@gmail.com 
233977Smax.romanov@gmail.com     unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count);
234977Smax.romanov@gmail.com     if (unit_jars == NULL) {
235977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for unit_jars array");
236977Smax.romanov@gmail.com 
237977Smax.romanov@gmail.com         return NXT_ERROR;
238977Smax.romanov@gmail.com     }
239977Smax.romanov@gmail.com 
240977Smax.romanov@gmail.com     system_jars_count = nxt_nitems(nxt_java_system_jars) - 1;
241977Smax.romanov@gmail.com 
242977Smax.romanov@gmail.com     system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count);
243977Smax.romanov@gmail.com     if (system_jars == NULL) {
244977Smax.romanov@gmail.com         nxt_alert(task, "failed to allocate buffer for system_jars array");
245977Smax.romanov@gmail.com 
246977Smax.romanov@gmail.com         return NXT_ERROR;
247977Smax.romanov@gmail.com     }
248977Smax.romanov@gmail.com 
249977Smax.romanov@gmail.com     if (c->options != NULL) {
250977Smax.romanov@gmail.com 
251977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
252977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->options, i);
253977Smax.romanov@gmail.com             if (value == NULL) {
254977Smax.romanov@gmail.com                 break;
255977Smax.romanov@gmail.com             }
256977Smax.romanov@gmail.com 
257977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
258977Smax.romanov@gmail.com 
259977Smax.romanov@gmail.com             opt = nxt_malloc(str.length + 1);
260977Smax.romanov@gmail.com             if (opt == NULL) {
261977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate jvm_opt");
262977Smax.romanov@gmail.com                 return NXT_ERROR;
263977Smax.romanov@gmail.com             }
264977Smax.romanov@gmail.com 
265977Smax.romanov@gmail.com             memcpy(opt, str.start, str.length);
266977Smax.romanov@gmail.com             opt[str.length] = '\0';
267977Smax.romanov@gmail.com 
268977Smax.romanov@gmail.com             jvm_opt[i].optionString = opt;
269977Smax.romanov@gmail.com         }
270977Smax.romanov@gmail.com     }
271977Smax.romanov@gmail.com 
272977Smax.romanov@gmail.com     if (c->classpath != NULL) {
273977Smax.romanov@gmail.com         classpath_count = nxt_conf_array_elements_count(c->classpath);
274977Smax.romanov@gmail.com         classpath_arr = nxt_malloc(classpath_count * sizeof(char *));
275977Smax.romanov@gmail.com 
276977Smax.romanov@gmail.com         for (i = 0; /* void */ ; i++) {
277977Smax.romanov@gmail.com             value = nxt_conf_get_array_element(c->classpath, i);
278977Smax.romanov@gmail.com             if (value == NULL) {
279977Smax.romanov@gmail.com                 break;
280977Smax.romanov@gmail.com             }
281977Smax.romanov@gmail.com 
282977Smax.romanov@gmail.com             nxt_conf_get_string(value, &str);
283977Smax.romanov@gmail.com 
284977Smax.romanov@gmail.com             opt_len = str.length + 1;
285977Smax.romanov@gmail.com 
286977Smax.romanov@gmail.com             char *sc = memchr(str.start, ':', str.length);
287977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] == '/') {
288977Smax.romanov@gmail.com                 opt_len += nxt_length("file:");
289977Smax.romanov@gmail.com             }
290977Smax.romanov@gmail.com 
291977Smax.romanov@gmail.com             opt = nxt_malloc(opt_len);
292977Smax.romanov@gmail.com             if (opt == NULL) {
293977Smax.romanov@gmail.com                 nxt_alert(task, "failed to allocate classpath");
294977Smax.romanov@gmail.com                 return NXT_ERROR;
295977Smax.romanov@gmail.com             }
296977Smax.romanov@gmail.com 
297977Smax.romanov@gmail.com             if (sc == NULL && str.start[0] != '/') {
298977Smax.romanov@gmail.com                 nxt_memcpy(opt, str.start, str.length);
299977Smax.romanov@gmail.com                 opt[str.length] = '\0';
300977Smax.romanov@gmail.com 
301977Smax.romanov@gmail.com                 real_path = realpath(opt, NULL);
302977Smax.romanov@gmail.com                 if (real_path == NULL) {
303977Smax.romanov@gmail.com                     nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno);
304977Smax.romanov@gmail.com                     return NXT_ERROR;
305977Smax.romanov@gmail.com                 }
306977Smax.romanov@gmail.com 
307977Smax.romanov@gmail.com                 real_path_len = nxt_strlen(real_path);
308977Smax.romanov@gmail.com 
309977Smax.romanov@gmail.com                 free(opt);
310977Smax.romanov@gmail.com 
311977Smax.romanov@gmail.com                 opt_len = nxt_length("file:") + real_path_len + 1;
312977Smax.romanov@gmail.com 
313977Smax.romanov@gmail.com                 opt = nxt_malloc(opt_len);
314977Smax.romanov@gmail.com                 if (opt == NULL) {
315977Smax.romanov@gmail.com                     nxt_alert(task, "failed to allocate classpath");
316977Smax.romanov@gmail.com                     return NXT_ERROR;
317977Smax.romanov@gmail.com                 }
318977Smax.romanov@gmail.com 
319977Smax.romanov@gmail.com             } else {
320977Smax.romanov@gmail.com                 real_path = (char *) str.start;  /* I love this cast! */
321977Smax.romanov@gmail.com                 real_path_len = str.length;
322977Smax.romanov@gmail.com             }
323977Smax.romanov@gmail.com 
324977Smax.romanov@gmail.com             classpath_arr[i] = opt;
325977Smax.romanov@gmail.com 
326977Smax.romanov@gmail.com             if (sc == NULL) {
327977Smax.romanov@gmail.com                 opt = nxt_cpymem(opt, "file:", nxt_length("file:"));
328977Smax.romanov@gmail.com             }
329977Smax.romanov@gmail.com 
330977Smax.romanov@gmail.com             opt = nxt_cpymem(opt, real_path, real_path_len);
331977Smax.romanov@gmail.com             *opt = '\0';
332977Smax.romanov@gmail.com         }
333977Smax.romanov@gmail.com 
334977Smax.romanov@gmail.com     } else {
335977Smax.romanov@gmail.com         classpath_count = 0;
336977Smax.romanov@gmail.com         classpath_arr = NULL;
337977Smax.romanov@gmail.com     }
338977Smax.romanov@gmail.com 
339977Smax.romanov@gmail.com     rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args);
340977Smax.romanov@gmail.com     if (rc != JNI_OK) {
341977Smax.romanov@gmail.com         nxt_alert(task, "failed to create Java VM: %d", (int) rc);
342977Smax.romanov@gmail.com         return NXT_ERROR;
343977Smax.romanov@gmail.com     }
344977Smax.romanov@gmail.com 
345977Smax.romanov@gmail.com     rc = nxt_java_initThread(env);
346977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
347977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initThread() failed");
348977Smax.romanov@gmail.com         goto env_failed;
349977Smax.romanov@gmail.com     }
350977Smax.romanov@gmail.com 
351977Smax.romanov@gmail.com     rc = nxt_java_initURLClassLoader(env);
352977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
353977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initURLClassLoader() failed");
354977Smax.romanov@gmail.com         goto env_failed;
355977Smax.romanov@gmail.com     }
356977Smax.romanov@gmail.com 
357977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars);
358977Smax.romanov@gmail.com     if (cl == NULL) {
359977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader failed");
360977Smax.romanov@gmail.com         goto env_failed;
361977Smax.romanov@gmail.com     }
362977Smax.romanov@gmail.com 
363977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
364977Smax.romanov@gmail.com 
365977Smax.romanov@gmail.com     cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl);
366977Smax.romanov@gmail.com     if (cl == NULL) {
367977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLClassLoader_parent failed");
368977Smax.romanov@gmail.com         goto env_failed;
369977Smax.romanov@gmail.com     }
370977Smax.romanov@gmail.com 
371977Smax.romanov@gmail.com     nxt_java_setContextClassLoader(env, cl);
372977Smax.romanov@gmail.com 
373977Smax.romanov@gmail.com     rc = nxt_java_initContext(env, cl);
374977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
375977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initContext() failed");
376977Smax.romanov@gmail.com         goto env_failed;
377977Smax.romanov@gmail.com     }
378977Smax.romanov@gmail.com 
379977Smax.romanov@gmail.com     rc = nxt_java_initRequest(env, cl);
380977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
381977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initRequest() failed");
382977Smax.romanov@gmail.com         goto env_failed;
383977Smax.romanov@gmail.com     }
384977Smax.romanov@gmail.com 
385977Smax.romanov@gmail.com     rc = nxt_java_initResponse(env, cl);
386977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
387977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initResponse() failed");
388977Smax.romanov@gmail.com         goto env_failed;
389977Smax.romanov@gmail.com     }
390977Smax.romanov@gmail.com 
391977Smax.romanov@gmail.com     rc = nxt_java_initInputStream(env, cl);
392977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
393977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initInputStream() failed");
394977Smax.romanov@gmail.com         goto env_failed;
395977Smax.romanov@gmail.com     }
396977Smax.romanov@gmail.com 
397977Smax.romanov@gmail.com     rc = nxt_java_initOutputStream(env, cl);
398977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
399977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_initOutputStream() failed");
400977Smax.romanov@gmail.com         goto env_failed;
401977Smax.romanov@gmail.com     }
402977Smax.romanov@gmail.com 
403977Smax.romanov@gmail.com     nxt_java_jni_init(env);
404977Smax.romanov@gmail.com     if (rc != NXT_UNIT_OK) {
405977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_jni_init() failed");
406977Smax.romanov@gmail.com         goto env_failed;
407977Smax.romanov@gmail.com     }
408977Smax.romanov@gmail.com 
409977Smax.romanov@gmail.com     classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
410977Smax.romanov@gmail.com     if (classpath == NULL) {
411977Smax.romanov@gmail.com         nxt_alert(task, "nxt_java_newURLs failed");
412977Smax.romanov@gmail.com         goto env_failed;
413977Smax.romanov@gmail.com     }
414977Smax.romanov@gmail.com 
4151684Smax.romanov@nginx.com     java_data.jvm = jvm;
4161684Smax.romanov@nginx.com     java_data.cl = cl;
4171488St.nateldemoura@f5.com     java_data.ctx = nxt_java_startContext(env, c->webapp, classpath);
4181684Smax.romanov@nginx.com     java_data.conf = c;
419977Smax.romanov@gmail.com 
420977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
421977Smax.romanov@gmail.com         nxt_alert(task, "Unhandled exception in application start");
422977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
423977Smax.romanov@gmail.com         return NXT_ERROR;
424977Smax.romanov@gmail.com     }
425977Smax.romanov@gmail.com 
4261684Smax.romanov@nginx.com     rc = nxt_java_init_threads(c);
4271684Smax.romanov@nginx.com     if (nxt_slow_path(rc == NXT_UNIT_ERROR)) {
4281684Smax.romanov@nginx.com         return NXT_ERROR;
4291684Smax.romanov@nginx.com     }
4301684Smax.romanov@nginx.com 
431*1980Smax.romanov@nginx.com     nxt_unit_default_init(task, &java_init, app_conf);
432977Smax.romanov@gmail.com 
433977Smax.romanov@gmail.com     java_init.callbacks.request_handler = nxt_java_request_handler;
4341157Smax.romanov@nginx.com     java_init.callbacks.websocket_handler = nxt_java_websocket_handler;
4351157Smax.romanov@nginx.com     java_init.callbacks.close_handler = nxt_java_close_handler;
4361684Smax.romanov@nginx.com     java_init.callbacks.ready_handler = nxt_java_ready_handler;
437977Smax.romanov@gmail.com     java_init.request_data_size = sizeof(nxt_java_request_data_t);
4381488St.nateldemoura@f5.com     java_init.data = &java_data;
4391684Smax.romanov@nginx.com     java_init.ctx_data = env;
440977Smax.romanov@gmail.com 
441977Smax.romanov@gmail.com     ctx = nxt_unit_init(&java_init);
442977Smax.romanov@gmail.com     if (nxt_slow_path(ctx == NULL)) {
443977Smax.romanov@gmail.com         nxt_alert(task, "nxt_unit_init() failed");
444977Smax.romanov@gmail.com         return NXT_ERROR;
445977Smax.romanov@gmail.com     }
446977Smax.romanov@gmail.com 
447977Smax.romanov@gmail.com     rc = nxt_unit_run(ctx);
4481684Smax.romanov@nginx.com 
4491684Smax.romanov@nginx.com     nxt_java_join_threads(ctx, c);
450977Smax.romanov@gmail.com 
4511488St.nateldemoura@f5.com     nxt_java_stopContext(env, java_data.ctx);
452977Smax.romanov@gmail.com 
453977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
454977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
455977Smax.romanov@gmail.com     }
456977Smax.romanov@gmail.com 
4571157Smax.romanov@nginx.com     nxt_unit_done(ctx);
4581157Smax.romanov@nginx.com 
459977Smax.romanov@gmail.com     (*jvm)->DestroyJavaVM(jvm);
460977Smax.romanov@gmail.com 
4611684Smax.romanov@nginx.com     exit(rc);
462977Smax.romanov@gmail.com 
463977Smax.romanov@gmail.com     return NXT_OK;
464977Smax.romanov@gmail.com 
465977Smax.romanov@gmail.com env_failed:
466977Smax.romanov@gmail.com 
467977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
468977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
469977Smax.romanov@gmail.com     }
470977Smax.romanov@gmail.com 
471977Smax.romanov@gmail.com     return NXT_ERROR;
472977Smax.romanov@gmail.com }
473977Smax.romanov@gmail.com 
474977Smax.romanov@gmail.com 
475977Smax.romanov@gmail.com static void
nxt_java_request_handler(nxt_unit_request_info_t * req)476977Smax.romanov@gmail.com nxt_java_request_handler(nxt_unit_request_info_t *req)
477977Smax.romanov@gmail.com {
478977Smax.romanov@gmail.com     JNIEnv                   *env;
479977Smax.romanov@gmail.com     jobject                  jreq, jresp;
480977Smax.romanov@gmail.com     nxt_java_data_t          *java_data;
481977Smax.romanov@gmail.com     nxt_java_request_data_t  *data;
482977Smax.romanov@gmail.com 
483977Smax.romanov@gmail.com     java_data = req->unit->data;
4841684Smax.romanov@nginx.com     env = req->ctx->data;
485977Smax.romanov@gmail.com     data = req->data;
486977Smax.romanov@gmail.com 
487977Smax.romanov@gmail.com     jreq = nxt_java_newRequest(env, java_data->ctx, req);
488977Smax.romanov@gmail.com     if (jreq == NULL) {
489977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Request instance");
490977Smax.romanov@gmail.com 
491977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
492977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
493977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
494977Smax.romanov@gmail.com         }
495977Smax.romanov@gmail.com 
496977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
497977Smax.romanov@gmail.com         return;
498977Smax.romanov@gmail.com     }
499977Smax.romanov@gmail.com 
500977Smax.romanov@gmail.com     jresp = nxt_java_newResponse(env, req);
501977Smax.romanov@gmail.com     if (jresp == NULL) {
502977Smax.romanov@gmail.com         nxt_unit_req_alert(req, "failed to create Response instance");
503977Smax.romanov@gmail.com 
504977Smax.romanov@gmail.com         if ((*env)->ExceptionCheck(env)) {
505977Smax.romanov@gmail.com             (*env)->ExceptionDescribe(env);
506977Smax.romanov@gmail.com             (*env)->ExceptionClear(env);
507977Smax.romanov@gmail.com         }
508977Smax.romanov@gmail.com 
509977Smax.romanov@gmail.com         (*env)->DeleteLocalRef(env, jreq);
510977Smax.romanov@gmail.com 
511977Smax.romanov@gmail.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
512977Smax.romanov@gmail.com         return;
513977Smax.romanov@gmail.com     }
514977Smax.romanov@gmail.com 
515977Smax.romanov@gmail.com     data->header_size = 10 * 1024;
516977Smax.romanov@gmail.com     data->buf_size = 32 * 1024; /* from Jetty */
517977Smax.romanov@gmail.com     data->jreq = jreq;
518977Smax.romanov@gmail.com     data->jresp = jresp;
519977Smax.romanov@gmail.com     data->buf = NULL;
520977Smax.romanov@gmail.com 
521977Smax.romanov@gmail.com     nxt_unit_request_group_dup_fields(req);
522977Smax.romanov@gmail.com 
523977Smax.romanov@gmail.com     nxt_java_service(env, java_data->ctx, jreq, jresp);
524977Smax.romanov@gmail.com 
525977Smax.romanov@gmail.com     if ((*env)->ExceptionCheck(env)) {
526977Smax.romanov@gmail.com         (*env)->ExceptionDescribe(env);
527977Smax.romanov@gmail.com         (*env)->ExceptionClear(env);
528977Smax.romanov@gmail.com     }
529977Smax.romanov@gmail.com 
530977Smax.romanov@gmail.com     if (!nxt_unit_response_is_init(req)) {
531977Smax.romanov@gmail.com         nxt_unit_response_init(req, 200, 0, 0);
532977Smax.romanov@gmail.com     }
533977Smax.romanov@gmail.com 
534977Smax.romanov@gmail.com     if (!nxt_unit_response_is_sent(req)) {
535977Smax.romanov@gmail.com         nxt_unit_response_send(req);
536977Smax.romanov@gmail.com     }
537977Smax.romanov@gmail.com 
538977Smax.romanov@gmail.com     if (data->buf != NULL) {
539977Smax.romanov@gmail.com         nxt_unit_buf_send(data->buf);
540977Smax.romanov@gmail.com 
541977Smax.romanov@gmail.com         data->buf = NULL;
542977Smax.romanov@gmail.com     }
543977Smax.romanov@gmail.com 
5441157Smax.romanov@nginx.com     if (nxt_unit_response_is_websocket(req)) {
5451157Smax.romanov@nginx.com         data->jreq = (*env)->NewGlobalRef(env, jreq);
5461157Smax.romanov@nginx.com         data->jresp = (*env)->NewGlobalRef(env, jresp);
5471157Smax.romanov@nginx.com 
5481157Smax.romanov@nginx.com     } else {
5491157Smax.romanov@nginx.com         nxt_unit_request_done(req, NXT_UNIT_OK);
5501157Smax.romanov@nginx.com     }
5511157Smax.romanov@nginx.com 
552977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jresp);
553977Smax.romanov@gmail.com     (*env)->DeleteLocalRef(env, jreq);
5541157Smax.romanov@nginx.com }
5551157Smax.romanov@nginx.com 
5561157Smax.romanov@nginx.com 
5571157Smax.romanov@nginx.com static void
nxt_java_websocket_handler(nxt_unit_websocket_frame_t * ws)5581157Smax.romanov@nginx.com nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws)
5591157Smax.romanov@nginx.com {
5601157Smax.romanov@nginx.com     void                     *b;
5611157Smax.romanov@nginx.com     JNIEnv                   *env;
5621157Smax.romanov@nginx.com     jobject                  jbuf;
5631157Smax.romanov@nginx.com     nxt_java_request_data_t  *data;
5641157Smax.romanov@nginx.com 
5651684Smax.romanov@nginx.com     env = ws->req->ctx->data;
5661157Smax.romanov@nginx.com     data = ws->req->data;
5671157Smax.romanov@nginx.com 
5681157Smax.romanov@nginx.com     b = malloc(ws->payload_len);
5691157Smax.romanov@nginx.com     if (b != NULL) {
5701157Smax.romanov@nginx.com         nxt_unit_websocket_read(ws, b, ws->payload_len);
5711157Smax.romanov@nginx.com 
5721157Smax.romanov@nginx.com         jbuf = (*env)->NewDirectByteBuffer(env, b, ws->payload_len);
5731157Smax.romanov@nginx.com         if (jbuf != NULL) {
5741157Smax.romanov@nginx.com             nxt_java_Request_websocket(env, data->jreq, jbuf,
5751157Smax.romanov@nginx.com                                        ws->header->opcode, ws->header->fin);
5761157Smax.romanov@nginx.com 
5771157Smax.romanov@nginx.com             if ((*env)->ExceptionCheck(env)) {
5781157Smax.romanov@nginx.com                 (*env)->ExceptionDescribe(env);
5791157Smax.romanov@nginx.com                 (*env)->ExceptionClear(env);
5801157Smax.romanov@nginx.com             }
5811157Smax.romanov@nginx.com 
5821157Smax.romanov@nginx.com             (*env)->DeleteLocalRef(env, jbuf);
5831157Smax.romanov@nginx.com         }
5841157Smax.romanov@nginx.com 
5851157Smax.romanov@nginx.com         free(b);
5861157Smax.romanov@nginx.com     }
5871157Smax.romanov@nginx.com 
5881157Smax.romanov@nginx.com     nxt_unit_websocket_done(ws);
5891157Smax.romanov@nginx.com }
5901157Smax.romanov@nginx.com 
5911157Smax.romanov@nginx.com 
5921157Smax.romanov@nginx.com static void
nxt_java_close_handler(nxt_unit_request_info_t * req)5931157Smax.romanov@nginx.com nxt_java_close_handler(nxt_unit_request_info_t *req)
5941157Smax.romanov@nginx.com {
5951157Smax.romanov@nginx.com     JNIEnv                   *env;
5961157Smax.romanov@nginx.com     nxt_java_request_data_t  *data;
5971157Smax.romanov@nginx.com 
5981684Smax.romanov@nginx.com     env = req->ctx->data;
5991157Smax.romanov@nginx.com     data = req->data;
6001157Smax.romanov@nginx.com 
6011157Smax.romanov@nginx.com     nxt_java_Request_close(env, data->jreq);
6021157Smax.romanov@nginx.com 
6031157Smax.romanov@nginx.com     (*env)->DeleteGlobalRef(env, data->jresp);
6041157Smax.romanov@nginx.com     (*env)->DeleteGlobalRef(env, data->jreq);
605977Smax.romanov@gmail.com 
606977Smax.romanov@gmail.com     nxt_unit_request_done(req, NXT_UNIT_OK);
607977Smax.romanov@gmail.com }
608977Smax.romanov@gmail.com 
6091684Smax.romanov@nginx.com 
6101684Smax.romanov@nginx.com static int
nxt_java_ready_handler(nxt_unit_ctx_t * ctx)6111684Smax.romanov@nginx.com nxt_java_ready_handler(nxt_unit_ctx_t *ctx)
6121684Smax.romanov@nginx.com {
6131684Smax.romanov@nginx.com     int                  res;
6141684Smax.romanov@nginx.com     uint32_t             i;
6151684Smax.romanov@nginx.com     nxt_java_data_t      *java_data;
6161684Smax.romanov@nginx.com     nxt_java_app_conf_t  *c;
6171684Smax.romanov@nginx.com 
6181684Smax.romanov@nginx.com     java_data = ctx->unit->data;
6191684Smax.romanov@nginx.com     c = java_data->conf;
6201684Smax.romanov@nginx.com 
6211684Smax.romanov@nginx.com     if (c->threads <= 1) {
6221684Smax.romanov@nginx.com         return NXT_UNIT_OK;
6231684Smax.romanov@nginx.com     }
6241684Smax.romanov@nginx.com 
6251684Smax.romanov@nginx.com     for (i = 0; i < c->threads - 1; i++) {
6261684Smax.romanov@nginx.com         res = pthread_create(&nxt_java_threads[i], nxt_java_thread_attr,
6271684Smax.romanov@nginx.com                              nxt_java_thread_func, ctx);
6281684Smax.romanov@nginx.com 
6291684Smax.romanov@nginx.com         if (nxt_fast_path(res == 0)) {
6301684Smax.romanov@nginx.com             nxt_unit_debug(ctx, "thread #%d created", (int) (i + 1));
6311684Smax.romanov@nginx.com 
6321684Smax.romanov@nginx.com         } else {
6331684Smax.romanov@nginx.com             nxt_unit_alert(ctx, "thread #%d create failed: %s (%d)",
6341684Smax.romanov@nginx.com                            (int) (i + 1), strerror(res), res);
6351684Smax.romanov@nginx.com 
6361684Smax.romanov@nginx.com             return NXT_UNIT_ERROR;
6371684Smax.romanov@nginx.com         }
6381684Smax.romanov@nginx.com     }
6391684Smax.romanov@nginx.com 
6401684Smax.romanov@nginx.com     return NXT_UNIT_OK;
6411684Smax.romanov@nginx.com }
6421684Smax.romanov@nginx.com 
6431684Smax.romanov@nginx.com 
6441684Smax.romanov@nginx.com static void *
nxt_java_thread_func(void * data)6451684Smax.romanov@nginx.com nxt_java_thread_func(void *data)
6461684Smax.romanov@nginx.com {
6471684Smax.romanov@nginx.com     int              rc;
6481684Smax.romanov@nginx.com     JavaVM           *jvm;
6491684Smax.romanov@nginx.com     JNIEnv           *env;
6501684Smax.romanov@nginx.com     nxt_unit_ctx_t   *main_ctx, *ctx;
6511684Smax.romanov@nginx.com     nxt_java_data_t  *java_data;
6521684Smax.romanov@nginx.com 
6531684Smax.romanov@nginx.com     main_ctx = data;
6541684Smax.romanov@nginx.com 
6551684Smax.romanov@nginx.com     nxt_unit_debug(main_ctx, "worker thread start");
6561684Smax.romanov@nginx.com 
6571684Smax.romanov@nginx.com     java_data = main_ctx->unit->data;
6581684Smax.romanov@nginx.com     jvm = java_data->jvm;
6591684Smax.romanov@nginx.com 
6601684Smax.romanov@nginx.com     rc = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
6611684Smax.romanov@nginx.com     if (rc != JNI_OK) {
6621684Smax.romanov@nginx.com         nxt_unit_alert(main_ctx, "failed to attach Java VM: %d", (int) rc);
6631684Smax.romanov@nginx.com         return NULL;
6641684Smax.romanov@nginx.com     }
6651684Smax.romanov@nginx.com 
6661684Smax.romanov@nginx.com     nxt_java_setContextClassLoader(env, java_data->cl);
6671684Smax.romanov@nginx.com 
6681684Smax.romanov@nginx.com     ctx = nxt_unit_ctx_alloc(main_ctx, env);
6691684Smax.romanov@nginx.com     if (nxt_slow_path(ctx == NULL)) {
6701684Smax.romanov@nginx.com         goto fail;
6711684Smax.romanov@nginx.com     }
6721684Smax.romanov@nginx.com 
6731684Smax.romanov@nginx.com     (void) nxt_unit_run(ctx);
6741684Smax.romanov@nginx.com 
6751684Smax.romanov@nginx.com     nxt_unit_done(ctx);
6761684Smax.romanov@nginx.com 
6771684Smax.romanov@nginx.com fail:
6781684Smax.romanov@nginx.com 
6791684Smax.romanov@nginx.com     (*jvm)->DetachCurrentThread(jvm);
6801684Smax.romanov@nginx.com 
6811684Smax.romanov@nginx.com     nxt_unit_debug(NULL, "worker thread end");
6821684Smax.romanov@nginx.com 
6831684Smax.romanov@nginx.com     return NULL;
6841684Smax.romanov@nginx.com }
6851684Smax.romanov@nginx.com 
6861684Smax.romanov@nginx.com 
6871684Smax.romanov@nginx.com static int
nxt_java_init_threads(nxt_java_app_conf_t * c)6881684Smax.romanov@nginx.com nxt_java_init_threads(nxt_java_app_conf_t *c)
6891684Smax.romanov@nginx.com {
6901684Smax.romanov@nginx.com     int                    res;
6911684Smax.romanov@nginx.com     static pthread_attr_t  attr;
6921684Smax.romanov@nginx.com 
6931684Smax.romanov@nginx.com     if (c->threads <= 1) {
6941684Smax.romanov@nginx.com         return NXT_UNIT_OK;
6951684Smax.romanov@nginx.com     }
6961684Smax.romanov@nginx.com 
6971684Smax.romanov@nginx.com     if (c->thread_stack_size > 0) {
6981684Smax.romanov@nginx.com         res = pthread_attr_init(&attr);
6991684Smax.romanov@nginx.com         if (nxt_slow_path(res != 0)) {
7001684Smax.romanov@nginx.com             nxt_unit_alert(NULL, "thread attr init failed: %s (%d)",
7011684Smax.romanov@nginx.com                            strerror(res), res);
7021684Smax.romanov@nginx.com 
7031684Smax.romanov@nginx.com             return NXT_UNIT_ERROR;
7041684Smax.romanov@nginx.com         }
7051684Smax.romanov@nginx.com 
7061684Smax.romanov@nginx.com         res = pthread_attr_setstacksize(&attr, c->thread_stack_size);
7071684Smax.romanov@nginx.com         if (nxt_slow_path(res != 0)) {
7081684Smax.romanov@nginx.com             nxt_unit_alert(NULL, "thread attr set stack size failed: %s (%d)",
7091684Smax.romanov@nginx.com                            strerror(res), res);
7101684Smax.romanov@nginx.com 
7111684Smax.romanov@nginx.com             return NXT_UNIT_ERROR;
7121684Smax.romanov@nginx.com         }
7131684Smax.romanov@nginx.com 
7141684Smax.romanov@nginx.com         nxt_java_thread_attr = &attr;
7151684Smax.romanov@nginx.com     }
7161684Smax.romanov@nginx.com 
7171684Smax.romanov@nginx.com     nxt_java_threads = nxt_unit_malloc(NULL,
7181684Smax.romanov@nginx.com                                        sizeof(pthread_t) * (c->threads - 1));
7191684Smax.romanov@nginx.com     if (nxt_slow_path(nxt_java_threads == NULL)) {
7201684Smax.romanov@nginx.com         nxt_unit_alert(NULL, "Failed to allocate thread id array");
7211684Smax.romanov@nginx.com 
7221684Smax.romanov@nginx.com         return NXT_UNIT_ERROR;
7231684Smax.romanov@nginx.com     }
7241684Smax.romanov@nginx.com 
7251684Smax.romanov@nginx.com     memset(nxt_java_threads, 0, sizeof(pthread_t) * (c->threads - 1));
7261684Smax.romanov@nginx.com 
7271684Smax.romanov@nginx.com     return NXT_UNIT_OK;
7281684Smax.romanov@nginx.com }
7291684Smax.romanov@nginx.com 
7301684Smax.romanov@nginx.com 
7311684Smax.romanov@nginx.com static void
nxt_java_join_threads(nxt_unit_ctx_t * ctx,nxt_java_app_conf_t * c)7321684Smax.romanov@nginx.com nxt_java_join_threads(nxt_unit_ctx_t *ctx, nxt_java_app_conf_t *c)
7331684Smax.romanov@nginx.com {
7341684Smax.romanov@nginx.com     int       res;
7351684Smax.romanov@nginx.com     uint32_t  i;
7361684Smax.romanov@nginx.com 
7371684Smax.romanov@nginx.com     if (nxt_java_threads == NULL) {
7381684Smax.romanov@nginx.com         return;
7391684Smax.romanov@nginx.com     }
7401684Smax.romanov@nginx.com 
7411684Smax.romanov@nginx.com     for (i = 0; i < c->threads - 1; i++) {
7421684Smax.romanov@nginx.com         if ((uintptr_t) nxt_java_threads[i] == 0) {
7431684Smax.romanov@nginx.com             continue;
7441684Smax.romanov@nginx.com         }
7451684Smax.romanov@nginx.com 
7461684Smax.romanov@nginx.com         res = pthread_join(nxt_java_threads[i], NULL);
7471684Smax.romanov@nginx.com 
7481684Smax.romanov@nginx.com         if (nxt_fast_path(res == 0)) {
7491684Smax.romanov@nginx.com             nxt_unit_debug(ctx, "thread #%d joined", (int) i);
7501684Smax.romanov@nginx.com 
7511684Smax.romanov@nginx.com         } else {
7521684Smax.romanov@nginx.com             nxt_unit_alert(ctx, "thread #%d join failed: %s (%d)",
7531684Smax.romanov@nginx.com                            (int) i, strerror(res), res);
7541684Smax.romanov@nginx.com         }
7551684Smax.romanov@nginx.com     }
7561684Smax.romanov@nginx.com 
7571684Smax.romanov@nginx.com     nxt_unit_free(ctx, nxt_java_threads);
7581684Smax.romanov@nginx.com }
7591684Smax.romanov@nginx.com 
7601684Smax.romanov@nginx.com 
761