/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This source file is part of SableVM. * * * * See the file "LICENSE" for the copyright information and for * * the terms and conditions for copying, distribution and * * modification of this source file. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Important Note: * * This implementation does not use any SableVM internals. * It should go into the Classpath libraries as an implementation * for Unix systems. * */ /* for waitpid */ #include #include /* for kill */ #include #include /* for waitpid and EINTR */ #include /* ---------------------------------------------------------------------- Java_java_lang_Class_nativeIsInstance ---------------------------------------------------------------------- */ /* * Class: java_lang_ProcessImpl * Method: nativeWaitFor * Signature: (IZ)I */ JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_nativeWaitFor (JNIEnv *_env, jobject this, jint pid, jboolean nonblocking) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); int status; /* status of child process */ int value; /* return value of waitpid */ /* * Unimplemented: An InterruptedException must be thrown if this * thread is interrupted while its waiting for * the process to terminate. * interrupt() has not been implemented yet. * */ if (nonblocking) { /* do not block */ value = waitpid (pid, &status, WNOHANG); if (value == -1) { /* to remove later */ perror ("Java_java_lang_ProcessImpl_nativeWaitFor"); return -2; } else if (value == 0) { /* process not done yet */ return -1; } else { if (WIFEXITED (status)) { /* exited normally */ return WEXITSTATUS (status); } else { return -2; } } } else { /* in case of Thread.interrupt() put info that we're sleeping */ _svmt_word old_interrupted_status, new_interrupted_status; do { old_interrupted_status = env->thread.interrupted_status; new_interrupted_status = old_interrupted_status; new_interrupted_status |= SVM_THREAD_INTERRUPTIBLE_BY_SIGNAL; new_interrupted_status &= ~SVM_THREAD_THROW_INTERRUPTED; } while (!_svmm_compare_and_swap (env->thread.interrupted_status, old_interrupted_status, new_interrupted_status)); /* wait for completion */ value = waitpid (pid, &status, 0); /* leave "sleeping section" */ do { old_interrupted_status = env->thread.interrupted_status; new_interrupted_status = old_interrupted_status; new_interrupted_status &= ~SVM_THREAD_INTERRUPTIBLE_BY_SIGNAL; new_interrupted_status &= ~SVM_THREAD_THROW_INTERRUPTED; } while (!_svmm_compare_and_swap (env->thread.interrupted_status, old_interrupted_status, new_interrupted_status)); if (old_interrupted_status & SVM_THREAD_THROW_INTERRUPTED) { /* Real interruption or not, but Thread.interrupted() thinks it has * interrupted us, so throw the InterruptedException as expected. */ return -3; } if (value == -1) { /* Note: Could be here because of an unblocked signal. * Check if interrupted, if yes throw InterruptedException. */ if (errno == EINTR) return -3; perror ("Java_java_lang_ProcessImpl_nativeWaitFor"); return -2; } else { if (WIFEXITED (status)) { return WEXITSTATUS (status); } else { return -2; } } } } /* * Class: java_lang_ProcessImpl * Method: nativeDestroy * Signature: (I)V */ JNIEXPORT void JNICALL Java_java_lang_ProcessImpl_nativeDestroy (JNIEnv *env, jobject this, jint pid) { /* * Note: We can safely ignore all errors as there is no way of * reporting them to the user program. And the only error * that is likely to happen is ESRCH (no process with that * pid, i.e. already terminated). * */ kill (pid, SIGKILL); }