00001 /*! 00002 * @file exit.c 00003 * 00004 * @brief Abort strategy functions for the JVM. 00005 * 00006 * This implementation uses two invocations of 00007 * @c @b setjmp(3)/longjmp(3) to perform non-local returns 00008 * from error conditions. 00009 * 00010 * Normal exit conditions are more likely to use a simple 00011 * @c @b return() instead of the error mechanism, but are 00012 * not inhibited from it except that returning the normal 00013 * @link #EXIT_MAIN_OKAY EXIT_MAIN_OKAY@endlink cannot occur due to the 00014 * design of @c @b longjmp(3), which will force 00015 * @link #EXIT_LONGJMP_ARGERROR EXIT_LONGJMP_ARGERROR@endlink instead. 00016 * 00017 * @link #exit_init() exit_init()@endlink must be invoked at a 00018 * higher level than where @link #pjvm pjvm@endlink is used to 00019 * access anything, namely, @c @b pjvm->xxx since the 00020 * main JVM structure cannot be initialized at the same time 00021 * it is being protected by a @b jmp_buf hook stored within it. 00022 * It typically will be armed at the very entry to the JVM and 00023 * will never be re-armed since it is global in its scope of coverage. 00024 * 00025 * @link #exit_exception_setup() exit_exception_setup()@endlink 00026 * has similar requirements. However, since it is involved more 00027 * closely with @link #jvm_init() jvm_init()@endlink, it is typically 00028 * invoked at the beginning of that function. Once initialization 00029 * proceeds and more and more facilities become available, it should 00030 * be re-armed to a new handler to reflect increased capability. Once 00031 * the virtual execution engine is ready, it should be re-armed to 00032 * manually run @link #JVMCLASS_JAVA_LANG_LINKAGEERROR 00033 * JVMCLASS_JAVA_LANG_LINKAGEERROR@endlink subclasses through 00034 * the virtual execution engine before shutting down the JVM. 00035 * 00036 * @link #exit_end_thread_setup() exit_end_thread_setup()@endlink 00037 * is not so much an error handler as a simplification of the JVM 00038 * inner loop execution in @link #opcode_run() opcode_run()@endlink 00039 * that eliminates the need for two of the tests needed for continuing 00040 * to run Java virtual instruction on this thread. It is invoked 00041 * only once, and that before the inner look @c @b while statement. 00042 * When a member of the Java @b return instruction group is 00043 * executed, then if the thread termination conditions have been 00044 * met, the @c @b longjmp(3) exits the loop non-locally. 00045 * 00046 * 00047 * @section Control 00048 * 00049 * \$URL: https://svn.apache.org/path/name/exit.c $ \$Id: exit.c 0 09/28/2005 dlydick $ 00050 * 00051 * Copyright 2005 The Apache Software Foundation 00052 * or its licensors, as applicable. 00053 * 00054 * Licensed under the Apache License, Version 2.0 ("the License"); 00055 * you may not use this file except in compliance with the License. 00056 * You may obtain a copy of the License at 00057 * 00058 * http://www.apache.org/licenses/LICENSE-2.0 00059 * 00060 * Unless required by applicable law or agreed to in writing, 00061 * software distributed under the License is distributed on an 00062 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 00063 * either express or implied. 00064 * 00065 * See the License for the specific language governing permissions 00066 * and limitations under the License. 00067 * 00068 * @version \$LastChangedRevision: 0 $ 00069 * 00070 * @date \$LastChangedDate: 09/28/2005 $ 00071 * 00072 * @author \$LastChangedBy: dlydick $ 00073 * Original code contributed by Daniel Lydick on 09/28/2005. 00074 * 00075 * @section Reference 00076 * 00077 */ 00078 00079 #include "arch.h" 00080 ARCH_COPYRIGHT_APACHE(exit, c, "$URL: https://svn.apache.org/path/name/exit.c $ $Id: exit.c 0 09/28/2005 dlydick $"); 00081 00082 00083 #include <setjmp.h> 00084 00085 #include "jvmcfg.h" 00086 #include "classfile.h" 00087 #include "jvm.h" 00088 00089 /*! 00090 * @brief Permit localized usage of @b EXIT_xxx symbols. 00091 */ 00092 #define I_AM_EXIT_C 00093 #include "exit.h" 00094 00095 /*! 00096 * @brief Return a descriptive name string for each exit code. 00097 * 00098 * 00099 * @param code Exit code @link #exit_code_enum enumeration@endlink 00100 * 00101 * 00102 * @returns Null-terminated string describing the exit code. 00103 * 00104 */ 00105 rchar *exit_get_name(exit_code_enum code) 00106 { 00107 switch(code) 00108 { 00109 case EXIT_MAIN_OKAY: return(EXIT_MAIN_OKAY_DESC); 00110 case EXIT_LONGJMP_ARGERROR: return(EXIT_LONGJMP_ARGERROR_DESC); 00111 case EXIT_ARGV_HELP: return(EXIT_ARGV_HELP_DESC); 00112 case EXIT_ARGV_VERSION: return(EXIT_ARGV_VERSION_DESC); 00113 case EXIT_ARGV_COPYRIGHT: return(EXIT_ARGV_COPYRIGHT_DESC); 00114 case EXIT_ARGV_LICENSE: return(EXIT_ARGV_LICENSE_DESC); 00115 case EXIT_ARGV_ENVIRONMENT: return(EXIT_ARGV_ENVIRONMENT_DESC); 00116 case EXIT_JVM_THREAD: return(EXIT_JVM_THREAD_DESC); 00117 case EXIT_JVM_CLASS: return(EXIT_JVM_CLASS_DESC); 00118 case EXIT_JVM_OBJECT: return(EXIT_JVM_OBJECT_DESC); 00119 case EXIT_JVM_METHOD: return(EXIT_JVM_METHOD_DESC); 00120 case EXIT_JVM_FIELD: return(EXIT_JVM_FIELD_DESC); 00121 case EXIT_JVM_ATTRIBUTE: return(EXIT_JVM_ATTRIBUTE_DESC); 00122 case EXIT_JVM_THROWABLE: return(EXIT_JVM_THROWABLE_DESC); 00123 case EXIT_JVM_SIGNAL: return(EXIT_JVM_SIGNAL_DESC); 00124 case EXIT_JVM_BYTECODE: return(EXIT_JVM_BYTECODE_DESC); 00125 case EXIT_JVM_GC: return(EXIT_JVM_GC_DESC); 00126 case EXIT_JVM_INTERNAL: return(EXIT_JVM_INTERNAL_DESC); 00127 case EXIT_HEAP_ALLOC: return(EXIT_HEAP_ALLOC_DESC); 00128 case EXIT_GC_ALLOC: return(EXIT_GC_ALLOC_DESC); 00129 case EXIT_THREAD_STACK: return(EXIT_THREAD_STACK_DESC); 00130 case EXIT_TIMESLICE_START: return(EXIT_TIMESLICE_START_DESC); 00131 case EXIT_TMPAREA_MKDIR: return(EXIT_TMPAREA_MKDIR_DESC); 00132 case EXIT_TMPAREA_RMDIR: return(EXIT_TMPAREA_RMDIR_DESC); 00133 case EXIT_CLASSPATH_JAR: return(EXIT_CLASSPATH_JAR_DESC); 00134 case EXIT_MANIFEST_JAR: return(EXIT_MANIFEST_JAR_DESC); 00135 default: return("unknown"); 00136 } 00137 } /* END of exit_get_name() */ 00138 00139 00140 /*! 00141 * Handler linkage for fatal errors. Does not need global visibility, 00142 * just needs file scope. 00143 */ 00144 static jmp_buf exit_general_failure; 00145 00146 00147 /*! 00148 * Handler linkage for @b LinkageError. Does not need global 00149 * visibility, just needs file scope. 00150 */ 00151 static jmp_buf exit_LinkageError; 00152 00153 00154 /*! 00155 * Class to run on non-local return. Give global visibility for use 00156 * by users of 00157 * @link #exit_throw_exception() exit_throw_exception()@endlink. 00158 */ 00159 rchar *exit_LinkageError_subclass; 00160 00161 00162 /*! 00163 * Thread where error occurred. Give global visibility for use by 00164 * users of 00165 * @link #exit_throw_exception() exit_throw_exception()@endlink. 00166 */ 00167 jvm_thread_index exit_LinkageError_thridx; 00168 00169 00170 /*! 00171 * @brief Global handler setup for fatal JVM errors-- implements 00172 * @c @b setjmp(3). 00173 * 00174 * @b Parameters: @link #rvoid rvoid@endlink 00175 * 00176 * 00177 * @returns From normal setup, integer @link 00178 #EXIT_MAIN_OKAY EXIT_MAIN_OKAY@endlink. Otherwise, 00179 * return error code from @link #exit_jvm() exit_jvm()@endlink, 00180 * typically using a code found in 00181 * @link jvm/src/exit.h exit.h@endlink 00182 */ 00183 00184 int exit_init() 00185 { 00186 /* Return point from @c @b longjmp(3) as declared in exit_jvm() */ 00187 return(setjmp(exit_general_failure)); 00188 00189 } /* END of exit_init() */ 00190 00191 00192 00193 /*! 00194 * @brief Global handler setup for fatal 00195 * @link jvm_init() jvm_init()@endlink errors and other 00196 * @c @b java.lang.Throwable events-- implements 00197 * @c @b setjmp(3). 00198 * 00199 * 00200 * Use this function to arm handler for throwing 00201 * @c @b java.lang.Error and @c @b java.lang.Exception 00202 * throwable events. 00203 * 00204 * @b Parameters: @link #rvoid rvoid@endlink 00205 * 00206 * 00207 * @returns From normal setup, integer 00208 * @link #EXIT_MAIN_OKAY EXIT_MAIN_OKAY@endlink. 00209 * Otherwise, return 00210 * @link #exit_code_enum exit code enumeration@endlink from 00211 * @link #exit_jvm() exit_jvm()@endlink. 00212 * 00213 */ 00214 00215 int exit_exception_setup(rvoid) 00216 { 00217 00218 exit_LinkageError_subclass = (rchar *) rnull; 00219 exit_LinkageError_thridx = jvm_thread_index_null; 00220 00221 /* 00222 * Return point from @c @b longjmp(3) as declared 00223 * in @link #exit_throw_exception() exit_throw_exception()@endlink 00224 */ 00225 return(setjmp(exit_LinkageError)); 00226 00227 } /* END of exit_exception_setup() */ 00228 00229 00230 /*! 00231 * @brief Global handler for initialization linkage errors, 00232 * per spec section 2.17.x -- implements @c @b longjmp(3). 00233 * 00234 * Use this function to throw @c @b java.lang.Error and 00235 * @c @b java.lang.Exception throwable events. 00236 * 00237 * This is a global handler invocation first for @link #jvm_init() 00238 jvm_init()@endlink during startup and then runtime events. 00239 * A @e wide variety of runtime conditions may be expressed in 00240 * the combination of @b rc and @b preason. Judicious combinations 00241 * of exit codes and error classes will greatly limit the need 00242 * for expanding on the number of values for either parameter, 00243 * yet can express many different nuances of errors. 00244 * 00245 * @param rcenum Return code to pass back out of failed routine, which 00246 * must be an 00247 * @link #exit_code_enum exit code enumeration@endlink 00248 * other than 00249 * @link #EXIT_MAIN_OKAY EXIT_MAIN_OKAY@endlink, which 00250 * will get translated into @link 00251 #EXIT_LONGJMP_ARGERROR EXIT_LONGJMP_ARGERROR@endlink. 00252 * 00253 * @param preason Error class, which must be a subclass of 00254 * @c @b java.lang.LinkageError , namely: 00255 * 00256 * <ul> <li> @link #JVMCLASS_JAVA_LANG_LINKAGEERROR 00257 JVMCLASS_JAVA_LANG_LINKAGEERROR@endlink </li> 00258 * <li> @link #JVMCLASS_JAVA_LANG_CLASSCIRCULARITYERROR 00259 JVMCLASS_JAVA_LANG_CLASSCIRCULARITYERROR@endlink </li> 00260 * <li> @link #JVMCLASS_JAVA_LANG_CLASSFORMATERROR 00261 JVMCLASS_JAVA_LANG_CLASSFORMATERROR@endlink </li> 00262 * <li> @link #JVMCLASS_JAVA_LANG_EXCEPTIONININITIALIZERERROR 00263 JVMCLASS_JAVA_LANG_EXCEPTIONININITIALIZERERROR@endlink </li> 00264 * <li> @link #JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR 00265 JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR@endlink </li> 00266 * <li> @link #JVMCLASS_JAVA_LANG_NOCLASSDEFFOUNDERROR 00267 JVMCLASS_JAVA_LANG_NOCLASSDEFFOUNDERROR@endlink </li> 00268 * <li> @link #JVMCLASS_JAVA_LANG_UNSATISFIEDLINKERROR 00269 JVMCLASS_JAVA_LANG_UNSATISFIEDLINKERROR@endlink </li> 00270 * <li> @link #JVMCLASS_JAVA_LANG_VERIFYERROR 00271 JVMCLASS_JAVA_LANG_VERIFYERROR@endlink </li> 00272 * </ul> 00273 * 00274 * @returns non-local state restoration from setup via @c @b setjmp(3) 00275 * as stored in @link 00276 #exit_LinkageError exit_LinkageError@endlink 00277 * buffer by @link #exit_init() exit_init()@endlink 00278 * in @link #jvm_init() jvm_init()@endlink before any of 00279 * these errors could occur. All code invoking this 00280 * function should use the standard @c @b lint(1) comment for 00281 * "code not reached" as shown after the @c @b longjmp(3) 00282 * function call in the source code of this function: 00283 * <b>/</b><b>*NOTREACHED*</b><b>/</b> 00284 * 00285 */ 00286 00287 rvoid exit_throw_exception(exit_code_enum rcenum, rchar *preason) 00288 { 00289 /* Report error class to handler */ 00290 exit_LinkageError_subclass = preason; 00291 exit_LinkageError_thridx = CURRENT_THREAD; 00292 00293 /* Returns to @c @b setjmp(3) */ 00294 int rc = (int) rcenum; 00295 longjmp(exit_LinkageError, rc); 00296 /*NOTREACHED*/ 00297 00298 } /* END of exit_throw_exception() */ 00299 00300 00301 /*! 00302 * @brief Global handler invocation for fatal JVM errors-- implements 00303 * @c @b longjmp(3) 00304 * 00305 * @param rcenum Return code to pass back out of JVM. 00306 * 00307 * 00308 * @returns non-local state restoration from setup via @c @b setjmp(3) 00309 * above as stored in @link 00310 #exit_general_failure exit_general_failure@endlink. 00311 * All code invoking this function should use the 00312 * standard @c @b lint(1) comment for "code not reached" as 00313 * shown after the @c @b longjmp(3) function call in 00314 * the source code of this function: 00315 * <b>/</b><b>*NOTREACHED*</b><b>/</b> 00316 */ 00317 00318 rvoid exit_jvm(exit_code_enum rcenum) 00319 { 00320 /* Returns to @c @b setjmp(3) as declared in exit_jvm() */ 00321 int rc = (int) rcenum; 00322 longjmp(exit_general_failure, rc); 00323 /*NOTREACHED*/ 00324 00325 } /* END of exit_jvm() */ 00326 00327 00328 /* EOF */ 00329