call must have returned).
Updated the examples tesh to match it.
Updated the changelog
org/simgrid/msg/MsgException.java
org/simgrid/msg/NativeException.java
org/simgrid/msg/Process.java
- org/simgrid/msg/ProcessKilled.java
+ org/simgrid/msg/ProcessKilledException.java
org/simgrid/msg/ProcessNotFoundException.java
org/simgrid/msg/Task.java
org/simgrid/msg/TaskCancelledException.java
* Add "sleep" in Process with Thread-like syntax/use.
* Change the way the Process are created in ApplicationHandler: a full
constructor is now needed for your child classes.
+ * Change the way Process are created: Process are no longer a Thread subclass.
-- $date Da SimGrid team <simgrid-devel@lists.gforge.inria.fr>
SimGrid-java (3.6) unstable; urgency=low
break;
}
}
-
process2.kill();
Msg.info("Process2 is now killed, should exit now");
Msg.info("Send Mail1!");
task.send("mail1");
- Msg.info("Send Mail2 !");
Task task2 = Task.receive("mail2");
Msg.info("Receive Mail2!");
}
! output sort
$ java -cp .:${srcdir:=.}/examples:${srcdir:=.}/simgrid.jar master_slave_kill/MsKill ${srcdir:=.}/examples/master_slave_kill/platform.xml
-> Thread-1: I ignore that other exception
> [0.000000] [jmsg/INFO] Ready to run MSG_MAIN
> [0.013010] [jmsg/INFO] Done running MSG_MAIN
> [0.013010] [jmsg/INFO] MSG_main finished
> [0.013010] [jmsg/INFO] Clean java world
> [0.013010] [jmsg/INFO] Clean native world
-> [0.013010] [jmsg/INFO] Process slave has been killed.
> [alice:slave:(2) 0.000000] [jmsg/INFO] Slave Hello!
> [alice:slave:(2) 0.000000] [jmsg/INFO] Send Mail1!
> [bob:master:(1) 0.000000] [jmsg/INFO] Master Hello!
> [bob:master:(1) 0.000000] [jmsg/INFO] Create process on host 'alice'
> [bob:master:(1) 0.013010] [jmsg/INFO] Received mail1!
-> [bob:master:(1) 0.013010] [jmsg/INFO] Process slave will be killed.
> [bob:master:(1) 0.013010] [jmsg/INFO] Process2 is now killed, should exit now
/** The arguments of the method function of the process. */
public Vector<String> args;
-
- /* process synchronization tools */
- private boolean nativeStop = false;
-
/**
* Default constructor (used in ApplicationHandler to initialize it)
*/
*
*/
public static native int killAll(int resetPID);
- /**
- * This method sets a flag to indicate that this thread must be killed. End user must use static method kill
- *
- * @return
- *
- */
- public void nativeStop() {
- nativeStop = true;
- }
- /**
- * getter for the flag that indicates that this thread must be killed
- *
- * @return
- *
- */
- public boolean getNativeStop() {
- return nativeStop;
- }
/**
* This method kill a process.
* @param process the process to be killed.
*
*/
- public void kill() {
- nativeStop();
- Msg.info("Process " + msgName() + " will be killed.");
- }
-
+ public native void kill();
/**
* Suspends the process by suspending the task on which it was
* waiting for the completion.
*
*/
public static native Process currentProcess();
- /**
- * Kills a MSG process
- * @param process Valid java process to kill
- */
- final static native void kill(Process process);
/**
* Migrates a process to another host.
*
Msg.info("Unexpected behavior. Stopping now");
System.exit(1);
}
- catch(ProcessKilled pk) {
- if (nativeStop) {
+ catch(ProcessKilledException pk) {
- }
- else {
- pk.printStackTrace();
- Msg.info("Unexpected behavior. Stopping now");
- System.exit(1);
- }
- }
+ }
}
/**
/** This exception class is only used to interrupt the java user code
* when the process gets killed by an external event */
-public class ProcessKilled extends RuntimeException {
+public class ProcessKilledException extends RuntimeException {
private static final long serialVersionUID = 1L;
-
+ public ProcessKilledException(String s) {
+ super(s);
+ }
}
jxbt_throw_native(env,bprintf("comm is null"));
return JNI_FALSE;
}
- if (MSG_comm_test(comm)) {
- MSG_error_t status = MSG_comm_get_status(comm);
- if (status == MSG_OK) {
- jcomm_bind_task(env,jcomm);
- return JNI_TRUE;
+ TRY {
+ if (MSG_comm_test(comm)) {
+ MSG_error_t status = MSG_comm_get_status(comm);
+ if (status == MSG_OK) {
+ jcomm_bind_task(env,jcomm);
+ return JNI_TRUE;
+ }
+ else {
+ //send the correct exception
+ jcomm_throw(env,status);
+ return JNI_FALSE;
+ }
}
else {
- //send the correct exception
- jcomm_throw(env,status);
return JNI_FALSE;
}
}
- else {
- return JNI_FALSE;
+ CATCH_ANONYMOUS {
+
}
+ return JNI_FALSE;
}
JNIEXPORT void JNICALL
Java_org_simgrid_msg_Comm_waitCompletion(JNIEnv *env, jobject jcomm, jdouble timeout) {
jxbt_throw_native(env,bprintf("comm is null"));
return;
}
-
- MSG_error_t status = MSG_comm_wait(comm,(double)timeout);
+ MSG_error_t status;
+ TRY {
+ status = MSG_comm_wait(comm,(double)timeout);
+ }
+ CATCH_ANONYMOUS {
+ return;
+ }
if (status == MSG_OK) {
jcomm_bind_task(env,jcomm);
return;
xbt_os_thread_join(context->thread,NULL);
}
-void jprocess_exit(jobject jprocess, JNIEnv * env)
-{
- jmethodID id =
- jxbt_get_smethod(env, "org/simgrid/msg/Process", "interrupt", "()V");
-
- if (!id)
- return;
-
- (*env)->CallVoidMethod(env, jprocess, id);
-}
-
void jprocess_start(jobject jprocess, JNIEnv * env)
{
jmethodID id =
XBT_INFO("Can't find bind field in Process");
return NULL;
}
-
return (m_process_t) (long) (*env)->GetLongField(env, jprocess, id);
}
void jprocess_bind(jobject jprocess, m_process_t process, JNIEnv * env)
{
jfieldID id = jxbt_get_sfield(env, "org/simgrid/msg/Process", "bind", "J");
- if (!id)
- return;
-
+ xbt_assert((id != NULL), "field bind not found in org/simgrid/msg/Process");
(*env)->SetLongField(env, jprocess, id, (jlong) (long) (process));
}
0,NULL,NULL);
MSG_process_set_data(process,&process);
+ /* bind the java process instance to the native process */
+ jprocess_bind(jprocess, process, env);
/* release our reference to the process name (variable name becomes invalid) */
//FIXME : This line should be uncommented but with mac it doesn't work. BIG WARNING
//(*env)->ReleaseStringUTFChars(env, jname, name);
(*env)->ReleaseStringUTFChars(env, jhostname, hostname);
- /* bind the java process instance to the native process */
- jprocess_bind(jprocess, process, env);
-
/* sets the PID and the PPID of the process */
(*env)->SetIntField(env, jprocess, jprocess_field_Process_pid,(jint) MSG_process_get_PID(process));
(*env)->SetIntField(env, jprocess, jprocess_field_Process_ppid, (jint) MSG_process_get_PPID(process));
}
JNIEXPORT void JNICALL
-Java_org_simgrid_msg_Process_kill(JNIEnv * env, jclass cls,
+Java_org_simgrid_msg_Process_kill(JNIEnv * env,
jobject jprocess)
{
- /* get the native instances from the java ones */
+ /* get the native instances from the java ones */
m_process_t process = jprocess_to_native_process(jprocess, env);
-
if (!process) {
jxbt_throw_notbound(env, "process", jprocess);
return;
}
+ /* Sets the "killed" flag to kill the process on the next unschedule */
+ smx_ctx_java_t context = (smx_ctx_java_t)MSG_process_get_smx_ctx(process);
+ context->killed = 1;
- /* kill the native process (this wrapper is call by the destructor of the java
- * process instance)
- */
- MSG_process_kill(process);
+ MSG_process_kill(process);
}
JNIEXPORT void JNICALL
Java_org_simgrid_msg_Process_migrate(JNIEnv * env,
*/
void jprocess_start(jobject jprocess, JNIEnv * env);
-/**
- * This function forces the java process to stop.
- *
- * @param jprocess The java process to stop.
- * @param env The env of the current thread
- *
- * @exception If the class Process is not found the function throws
- * the ClassNotFoundException. If the methos stop() of
- * this class is not found the function throws the exception
- * NotSuchMethodException.
- */
-void jprocess_exit(jobject jprocess, JNIEnv * env);
-
/**
* This function associated a native process to a java process instance.
*
* Signature (Lsimgrid/msg/Process;)V
*/
JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_kill
- (JNIEnv *, jclass, jobject);
+ (JNIEnv *, jobject);
/*
* Class org_simgrid_msg_Process
}
alias = (*env)->GetStringUTFChars(env, jalias, 0);
-
- rv = MSG_task_receive_ext(&task, alias, (double) jtimeout, host);
+ TRY {
+ rv = MSG_task_receive_ext(&task, alias, (double) jtimeout, host);
+ }
+ CATCH_ANONYMOUS {
+ return NULL;
+ }
if (rv != MSG_OK) {
switch (rv) {
case MSG_TIMEOUT:
int rv;
alias = (*env)->GetStringUTFChars(env, jalias, 0);
-
- rv = MSG_task_listen(alias);
-
+ TRY {
+ rv = MSG_task_listen(alias);
+ }
+ CATCH_ANONYMOUS {
+ return 0;
+ }
(*env)->ReleaseStringUTFChars(env, jalias, alias);
return (jboolean) rv;
return -1;
}
alias = (*env)->GetStringUTFChars(env, jalias, 0);
-
- rv = MSG_task_listen_from_host(alias, host);
-
+ TRY {
+ rv = MSG_task_listen_from_host(alias, host);
+ }
+ CATCH_ANONYMOUS {
+ return 0;
+ }
(*env)->ReleaseStringUTFChars(env, jalias, alias);
return (jint) rv;
int rv;
const char *alias = (*env)->GetStringUTFChars(env, jalias, 0);
-
- rv = MSG_task_listen_from(alias);
-
+ TRY {
+ rv = MSG_task_listen_from(alias);
+ }
+ CATCH_ANONYMOUS {
+ return 0;
+ }
(*env)->ReleaseStringUTFChars(env, jalias, alias);
return (jint) rv;
/* ***************** */
/* EXCEPTION RAISING */
/* ***************** */
-static void jxbt_throw_by_name(JNIEnv * env, const char *name, char *msg)
+void jxbt_throw_by_name(JNIEnv * env, const char *name, char *msg)
{
jclass cls = (*env)->FindClass(env, name);
jxbt_throw_task_cancelled(env,detail); \
} } while (0)
+/* Throws an exception according to its name */
+void jxbt_throw_by_name(JNIEnv * env, const char *name, char *msg);
/** Thrown on internal error of this layer, or on problem with JNI */
void jxbt_throw_jni(JNIEnv * env, const char *msg);
/** Thrown when using an object not bound to a native one where it should, or reverse (kinda JNI issue) */
#include <xbt/function_types.h>
#include <simgrid/simix.h>
+#include <xbt/ex.h>
#include "smx_context_java.h"
#include "jxbt_utilities.h"
#include "xbt/dynar.h"
context->jprocess = (jobject) code;
context->begin = xbt_os_sem_init(0);
context->end = xbt_os_sem_init(0);
+ context->killed = 0;
context->thread = xbt_os_thread_create(NULL,smx_ctx_java_thread_run,context,NULL);
}
else {
jmethodID id = jxbt_get_smethod(env, "org/simgrid/msg/Process", "run", "()V");
xbt_assert( (id != NULL), "Method not found...");
(*env)->CallVoidMethod(env, context->jprocess, id);
-
smx_ctx_java_stop((smx_context_t)context);
return NULL;
xbt_assert(context == my_current_context,
"The context to stop must be the current one");
/* I am the current process and I am dying */
- smx_ctx_base_stop(context);
- /* detach the thread and kills it */
- JNIEnv *env = ctx_java->jenv;
- (*env)->DeleteGlobalRef(env,ctx_java->jprocess);
- JavaVM *jvm = get_current_vm();
- jint error = (*jvm)->DetachCurrentThread(jvm);
- xbt_assert((error == JNI_OK), "The thread couldn't be detached.");
- xbt_os_sem_release(((smx_ctx_java_t)context)->end);
- xbt_os_thread_exit(NULL);
+ if (ctx_java->killed == 1) {
+ ctx_java->killed = 0;
+ JNIEnv *env = get_current_thread_env();
+ jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledException", bprintf("Process killed :)"));
+ THROWF(cancel_error, 0, "process cancelled");
+ }
+ else {
+ smx_ctx_base_stop(context);
+ /* detach the thread and kills it */
+ JNIEnv *env = ctx_java->jenv;
+ (*env)->DeleteGlobalRef(env,ctx_java->jprocess);
+ JavaVM *jvm = get_current_vm();
+ jint error = (*jvm)->DetachCurrentThread(jvm);
+ xbt_assert((error == JNI_OK), "The thread couldn't be detached.");
+ xbt_os_sem_release(((smx_ctx_java_t)context)->end);
+ xbt_os_thread_exit(NULL);
+
+ }
}
static void smx_ctx_java_suspend(smx_context_t context)
{
XBT_DEBUG("XXXX Context Resume\n");
smx_ctx_java_t ctx_java = (smx_ctx_java_t) new_context;
- xbt_os_sem_release(ctx_java->begin);
+ xbt_os_sem_release(ctx_java->begin);
xbt_os_sem_acquire(ctx_java->end);
}
xbt_os_thread_t thread;
xbt_os_sem_t begin; /* this semaphore is used to schedule/yield the process */
xbt_os_sem_t end; /* this semaphore is used to schedule/unschedule the process */
+ int killed;
} s_smx_ctx_java_t, *smx_ctx_java_t;
void SIMIX_ctx_java_factory_init(smx_context_factory_t *factory);