ADD_TESH_FACTORIES(msg-sendrecv-Vegas "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Vegas.tesh)
ADD_TESH_FACTORIES(msg-sendrecv-Reno "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/sendrecv/sendrecv_Reno.tesh)
ADD_TESH_FACTORIES(msg-suspend "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/suspend/suspend.tesh)
+ ADD_TESH_FACTORIES(msg-exception "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/exception/exception.tesh)
ADD_TESH_FACTORIES(msg-pmm "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/pmm/pmm.tesh)
ADD_TESH_FACTORIES(msg-masterslave-bypass "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/masterslave/masterslave_bypass.tesh)
ADD_TESH_FACTORIES(msg-masterslave-kill "thread;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/masterslave/masterslave_kill.tesh)
static int victim(int argc, char *argv[]) {
xbt_ex_t e;
- XBT_INFO("Let's get suspended.");
+ msg_error_t res = MSG_OK;
+
+ XBT_INFO("Let's work.");
TRY {
- MSG_process_suspend(MSG_process_self());
+ res = MSG_task_execute(MSG_task_create("Task", 1e14, 0, NULL));
+ if (res != MSG_OK) {
+ XBT_INFO("The MSG_task_execute caught the exception for me and returned %d)",res);
+ } else {
+ xbt_die("I was expecting an exception during my execution!");
+ }
} CATCH(e) {
XBT_INFO("The received exception resumed my execution. Good. Here is it: ----------------------->8----");
xbt_ex_display(&e);
xbt_ex_free(e);
}
- msg_error_t res = MSG_OK;
+
+ XBT_INFO("Let's get suspended.");
int gotit = 0;
+ TRY {
+ MSG_process_suspend(MSG_process_self());
+ } CATCH(e) {
+ XBT_INFO("The received exception resumed my suspension. Good. Here is it: ----------------------->8----");
+ xbt_ex_display(&e);
+ XBT_INFO("(end of the second exception) ----8<------------------------");
+ gotit = 1;
+ xbt_ex_free(e);
+ }
+ if(!gotit) {
+ xbt_die("I was expecting an exception during my suspension!");
+ }
+
XBT_INFO("Let's sleep for 10 seconds.");
TRY {
res = MSG_process_sleep(10);
+ if (res != MSG_OK) {
+ XBT_INFO("The MSG_process_sleep caught the exception for me and returned %d)",res);
+ } else {
+ xbt_die("I was expecting to get an exception during my nap.");
+ }
} CATCH(e) {
XBT_INFO("Got the second exception: ----------------------->8----");
xbt_ex_display(&e);
- XBT_INFO("(end of the second exception) ----8<------------------------");
+ XBT_INFO("(end of the third exception) ----8<------------------------");
xbt_ex_free(e);
}
- if (res != MSG_TASK_CANCELED)
- xbt_die("Sleep action not canceled through the exception. This is not a method. (retval: %d)",res);
- if (!gotit)
- xbt_die("I was expecting to get an exception during my nap.");
- XBT_INFO("My little nap got canceled through a raw exception. Excellent.");
+ XBT_INFO("Let's try a last time to do something on something");
+ MSG_process_sleep(10);
XBT_INFO("That's enough now. I quit.");
+
return 0;
}
XBT_INFO("Let's create a victim.");
victim_process = MSG_process_create("victim", victim, NULL, MSG_host_self());
+
+ XBT_INFO("Going to sleep for 1 second");
if (MSG_process_sleep(1) != MSG_OK)
xbt_die("What's going on??? I failed to sleep!");
XBT_INFO("Send a first exception (host failure)");
- SIMIX_process_throw(victim_process, host_error, 0, "Let's pretend that the host failed");
+ SIMIX_process_throw(victim_process, host_error, 0, "First Trick: Let's pretend that the host failed");
+
+
+ XBT_INFO("Sweet, let's prepare a second trick!");
+ XBT_INFO("Going to sleep for 2 seconds");
+
+ if (MSG_process_sleep(2) != MSG_OK)
+ xbt_die("What's going on??? I failed to sleep!");
+ XBT_INFO("Send a second exception (host failure)");
+ SIMIX_process_throw(victim_process, host_error, 0, "Second Trick: Let's pretend again that the host failed");
+
+ XBT_INFO("Sweet, let's prepare a third trick!");
+ XBT_INFO("Going to sleep for 3 seconds");
if (MSG_process_sleep(3) != MSG_OK)
xbt_die("What's going on??? I failed to sleep!");
- XBT_INFO("Send a second exception (cancellation)");
- SIMIX_process_throw(victim_process, cancel_error, 0, "Let's pretend this time that someone canceled something");
+ XBT_INFO("Send a third exception (cancellation)");
+ SIMIX_process_throw(victim_process, cancel_error, 0, "Third Trick: Let's pretend this time that someone canceled something");
XBT_INFO("OK, goodbye now.");
return 0;
! output sort
$ $SG_TEST_EXENV exception/exception ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/exception/deployment_exception.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
+> [ 0.000000] (1:terrorist@Jacquelin) Let's create a victim.
+> [ 0.000000] (2:victim@Jacquelin) Let's work.
+> [ 0.000000] (1:terrorist@Jacquelin) Going to sleep for 1 second
+> [ 1.000000] (1:terrorist@Jacquelin) Send a first exception (host failure)
+> [ 1.000000] (1:terrorist@Jacquelin) Sweet, let's prepare a second trick!
+> [ 1.000000] (1:terrorist@Jacquelin) Going to sleep for 2 seconds
+> [ 1.000000] (2:victim@Jacquelin) The MSG_task_execute caught the exception for me and returned 8)
+> [ 1.000000] (2:victim@Jacquelin) Let's get suspended.
+> [ 3.000000] (1:terrorist@Jacquelin) Send a second exception (host failure)
+> [ 3.000000] (1:terrorist@Jacquelin) Sweet, let's prepare a third trick!
+> [ 3.000000] (1:terrorist@Jacquelin) Going to sleep for 3 seconds
+> [ 3.000000] (2:victim@Jacquelin) The received exception resumed my suspension. Good. Here is it: ----------------------->8----
+> ** SimGrid: UNCAUGHT EXCEPTION received on exception/exception(2): category: action canceled; value: 0
+> ** Canceled
+> ** Thrown by () on process 0
+> [ 3.000000] (2:victim@Jacquelin) Canceled
+>
+> ** In SIMIX_execution_finish() at /home/alegrand/Work/SimGrid/simgrid-git/src/simix/smx_host.c:557
+> ** In SIMIX_post_host_execute() at /home/alegrand/Work/SimGrid/simgrid-git/src/simix/smx_host.c:604
+> ** In SIMIX_simcall_exit() at /home/alegrand/Work/SimGrid/simgrid-git/src/simix/popping.c:39
+> ** In SIMIX_run() at /home/alegrand/Work/SimGrid/simgrid-git/src/simix/smx_global.c:410
+> ** In MSG_main() at /home/alegrand/Work/SimGrid/simgrid-git/src/msg/msg_global.c:129
+> ** In main() at /home/alegrand/Work/SimGrid/simgrid-git/examples/msg/exception/exception.c:156
+> [ 3.000000] (2:victim@Jacquelin) (end of the second exception) ----8<------------------------
+> [ 3.000000] (2:victim@Jacquelin) Let's sleep for 10 seconds.
+> [ 6.000000] (1:terrorist@Jacquelin) Send a third exception (cancellation)
+> [ 6.000000] (1:terrorist@Jacquelin) OK, goodbye now.
+> [ 6.000000] (2:victim@Jacquelin) The MSG_process_sleep caught the exception for me and returned 8)
+> [ 6.000000] (2:victim@Jacquelin) Let's try a last time to do something on something
+> [ 16.000000] (2:victim@Jacquelin) That's enough now. I quit.
+> [ 16.000000] (0:@) Simulation time 16
#define MPI_IN_PLACE (void *)-222
// errorcodes
-#define MPI_SUCCESS 0
-#define MPI_ERR_COMM 1
-#define MPI_ERR_ARG 2
-#define MPI_ERR_TYPE 3
-#define MPI_ERR_REQUEST 4
-#define MPI_ERR_INTERN 5
-#define MPI_ERR_COUNT 6
-#define MPI_ERR_RANK 7
-#define MPI_ERR_TAG 8
-#define MPI_ERR_TRUNCATE 9
-#define MPI_ERR_GROUP 10
-#define MPI_ERR_OP 11
-#define MPI_ERR_OTHER 12
-#define MPI_ERR_IN_STATUS 13
-#define MPI_ERR_PENDING 14
-#define MPI_ERR_BUFFER 15
-#define MPI_ERR_NAME 16
-#define MPI_ERR_DIMS 17
-#define MPI_ERR_TOPOLOGY 18
-#define MPI_ERR_NO_MEM 19
-#define MPI_ERR_WIN 20
-#define MPI_ERR_INFO_VALUE 21
-#define MPI_ERR_INFO_KEY 22
-#define MPI_ERR_INFO_NOKEY 23
+#define MPI_SUCCESS 0
+#define MPI_ERR_COMM 1
+#define MPI_ERR_ARG 2
+#define MPI_ERR_TYPE 3
+#define MPI_ERR_REQUEST 4
+#define MPI_ERR_INTERN 5
+#define MPI_ERR_COUNT 6
+#define MPI_ERR_RANK 7
+#define MPI_ERR_TAG 8
+#define MPI_ERR_TRUNCATE 9
+#define MPI_ERR_GROUP 10
+#define MPI_ERR_OP 11
+#define MPI_ERR_OTHER 12
+#define MPI_ERR_IN_STATUS 13
+#define MPI_ERR_PENDING 14
+#define MPI_ERR_BUFFER 15
+#define MPI_ERR_NAME 16
+#define MPI_ERR_DIMS 17
+#define MPI_ERR_TOPOLOGY 18
+#define MPI_ERR_NO_MEM 19
+#define MPI_ERR_WIN 20
+#define MPI_ERR_INFO_VALUE 21
+#define MPI_ERR_INFO_KEY 22
+#define MPI_ERR_INFO_NOKEY 23
+#define MPI_ERR_ROOT 24
+#define MPI_ERR_UNKNOWN 25
+#define MPI_ERR_KEYVAL 26
+#define MPI_ERR_BASE 27
+#define MPI_ERR_SPAWN 28
+#define MPI_ERR_PORT 29
+#define MPI_ERR_SERVICE 30
+#define MPI_ERR_SIZE 31
+#define MPI_ERR_DISP 32
+#define MPI_ERR_INFO 33
+#define MPI_ERR_LOCKTYPE 34
+#define MPI_ERR_ASSERT 35
+#define MPI_RMA_CONFLICT 36
+#define MPI_RMA_SYNC 37
+#define MPI_ERR_FILE 38
+#define MPI_ERR_NOT_SAME 39
+#define MPI_ERR_AMODE 40
+#define MPI_ERR_UNSUPPORTED_DATAREP 41
+#define MPI_ERR_UNSUPPORTED_OPERATION 42
+#define MPI_ERR_NO_SUCH_FILE 43
+#define MPI_ERR_FILE_EXISTS 44
+#define MPI_ERR_BAD_FILE 45
+#define MPI_ERR_ACCESS 46
+#define MPI_ERR_NO_SPACE 47
+#define MPI_ERR_QUOTA 48
+#define MPI_ERR_READ_ONLY 49
+#define MPI_ERR_FILE_IN_USE 50
+#define MPI_ERR_DUP_DATAREP 51
+#define MPI_ERR_CONVERSION 52
+#define MPI_ERR_IO 53
+#define MPI_ERR_RMA_ATTACH 54
+#define MPI_ERR_RMA_CONFLICT 55
+#define MPI_ERR_RMA_RANGE 56
+#define MPI_ERR_RMA_SHARED 57
+#define MPI_ERR_RMA_SYNC 58
+#define MPI_ERR_RMA_FLAVOR 59
+#define MPI_T_ERR_CANNOT_INIT 60
+#define MPI_T_ERR_NOT_INITIALIZED 61
+#define MPI_T_ERR_MEMORY 62
+#define MPI_T_ERR_INVALID_INDEX 63
+#define MPI_T_ERR_INVALID_ITEM 64
+#define MPI_T_ERR_INVALID_SESSION 65
+#define MPI_T_ERR_INVALID_HANDLE 66
+#define MPI_T_ERR_OUT_OF_HANDLES 67
+#define MPI_T_ERR_OUT_OF_SESSIONS 68
+#define MPI_T_ERR_CVAR_SET_NOT_NOW 69
+#define MPI_T_ERR_CVAR_SET_NEVER 70
+#define MPI_T_ERR_PVAR_NO_WRITE 71
+#define MPI_T_ERR_PVAR_NO_STARTSTOP 72
+#define MPI_T_ERR_PVAR_NO_ATOMIC 73
+
+
#define MPI_ERRCODES_IGNORE (int *)0
#define MPI_IDENT 0
#define MPI_SIMILAR 1
#define MPI_NULL_DELETE_FN NULL
#define MPI_APPNUM 0
#define MPI_LASTUSEDCODE MPI_SUCCESS
-#define MPI_ERR_LASTCODE MPI_SUCCESS
+#define MPI_ERR_LASTCODE 74
#define MPI_CXX_BOOL MPI_DATATYPE_NULL
#define MPI_CXX_FLOAT_COMPLEX MPI_DATATYPE_NULL
Java_org_simgrid_msg_VM_internalmig(JNIEnv *env, jobject jvm, jobject jhost) {
msg_vm_t vm = jvm_get_native(env,jvm);
msg_host_t host = jhost_get_native(env, jhost);
+ xbt_ex_t e;
TRY{
MSG_vm_migrate(vm,host);
- } CATCH_ANONYMOUS{
- XBT_INFO("CATCH EXCEPTION MIGRATION");
- jxbt_throw_host_failure(env, (char*)"during migration");
+ } CATCH(e){
+ XBT_INFO("CATCH EXCEPTION MIGRATION %s",e.msg);
+ xbt_ex_free(e);
+ jxbt_throw_host_failure(env, (char*)"during migration");
}
}
try {
this.internalmig(destination);
} catch (Exception e){
- Msg.info("an exception occurs during the migration of VM "+this.getName());
- throw new HostFailureException();
+ Msg.info("Migration of VM "+this.getName()+" to "+destination.getName()+" is impossible ("+e.getMessage()+")");
+ throw new HostFailureException();
}
// If the migration correcly returned, then we should change the currentHost value.
this.currentHost = destination;
sg_size_t sent = 0;
double clock_prev_send = MSG_get_clock();
TRY {
- XBT_INFO("Stage 2, gonna send %llu", updated_size);
+ XBT_DEBUG("Stage 2, gonna send %llu", updated_size);
sent = send_migration_data(ms->vm, ms->src_pm, ms->dst_pm, updated_size, ms->mbox, 2, stage2_round, mig_speed, mig_timeout);
} CATCH_ANONYMOUS {
//hostfailure (if you want to know whether this is the SRC or the DST please check directly in send_migration_data code)
stop_dirty_page_tracking(ms->vm);
TRY {
- XBT_INFO("Stage 3: Gonna send %f", remaining_size);
+ XBT_DEBUG("Stage 3: Gonna send %f", remaining_size);
send_migration_data(ms->vm, ms->src_pm, ms->dst_pm, remaining_size, ms->mbox, 3, 0, mig_speed, -1);
} CATCH_ANONYMOUS {
//hostfailure (if you want to know whether this is the SRC or the DST please check directly in send_migration_data code)
}
// At that point the Migration is considered valid for the SRC node but remind that the DST side should relocate effectively the VM on the DST node.
- XBT_INFO("mig: tx_done");
+ XBT_DEBUG("mig: tx_done");
return 0;
}
msg_host_t old_pm = simcall_vm_get_pm(vm);
+ if(MSG_host_is_off(old_pm))
+ THROWF(vm_error, 0, "SRC host(%s) seems off, cannot start a migration", sg_host_name(old_pm));
+
+ if(MSG_host_is_off(new_pm))
+ THROWF(vm_error, 0, "DST host(%s) seems off, cannot start a migration", sg_host_name(new_pm));
+
if (!MSG_vm_is_running(vm))
THROWF(vm_error, 0, "VM(%s) is not running", sg_host_name(vm));
unsigned int cursor;
xbt_dynar_foreach(simix_global->process_to_run, cursor, process) {
+ XBT_DEBUG("Handling %p",process);
xbt_os_sem_release(((smx_ctx_thread_t) process->context)->begin);
xbt_os_sem_acquire(((smx_ctx_thread_t) process->context)->end);
}
SIMIX_simcall_handle(&process->simcall, 0);
}
}
+ /* Wake up all processes waiting for a Surf action to finish */
+ xbt_dynar_foreach(model_list, iter, model) {
+ XBT_DEBUG("Handling process whose action failed");
+ while ((action = surf_model_extract_failed_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
+ SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
+ }
+ XBT_DEBUG("Handling process whose action terminated normally");
+ while ((action = surf_model_extract_done_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
+ if (surf_action_get_data(action) == NULL)
+ XBT_DEBUG("probably vcpu's action %p, skip", action);
+ else
+ SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
+ }
+ }
}
time = SIMIX_timer_next();
- if (time != -1.0 || xbt_swag_size(simix_global->process_list) != 0)
+ if (time != -1.0 || xbt_swag_size(simix_global->process_list) != 0) {
+ XBT_DEBUG("Calling surf_solve");
time = surf_solve(time);
-
+ XBT_DEBUG("Moving time ahead : %g", time);
+ }
/* Notify all the hosts that have failed */
/* FIXME: iterate through the list of failed host and mark each of them */
/* as failed. On each host, signal all the running processes with host_fail */
/* Wake up all processes waiting for a Surf action to finish */
xbt_dynar_foreach(model_list, iter, model) {
- while ((action = surf_model_extract_failed_action_set(model)))
+ XBT_DEBUG("Handling process whose action failed");
+ while ((action = surf_model_extract_failed_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
-
- while ((action = surf_model_extract_done_action_set(model)))
+ }
+ XBT_DEBUG("Handling process whose action terminated normally");
+ while ((action = surf_model_extract_done_action_set(model))) {
+ XBT_DEBUG(" Handling Action %p",action);
if (surf_action_get_data(action) == NULL)
XBT_DEBUG("probably vcpu's action %p, skip", action);
else
SIMIX_simcall_exit((smx_synchro_t) surf_action_get_data(action));
+ }
}
/* Autorestart all process */
}
}
+ XBT_DEBUG("%p should not be run anymore",process);
xbt_swag_remove(process, simix_global->process_list);
xbt_swag_remove(process, SIMIX_host_priv(process->smx_host)->process_list);
xbt_swag_insert(process, simix_global->process_to_destroy);
smx_process_t process = NULL;
while ((process = xbt_swag_extract(simix_global->process_to_destroy))) {
+ XBT_DEBUG("Getting rid of %p",process);
+
SIMIX_context_free(process->context);
/* Free the exception allocated at creation time */
}
}
if(!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != issuer) {
+ XBT_DEBUG("Inserting %s in the to_run list", process->name);
xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
}
break;
case SIMIX_SYNC_SLEEP:
- SIMIX_process_sleep_destroy(process->waiting_synchro);
- break;
-
case SIMIX_SYNC_JOIN:
SIMIX_process_sleep_destroy(process->waiting_synchro);
+ if (!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != SIMIX_process_self()) {
+ XBT_DEBUG("Inserting %s in the to_run list", process->name);
+ xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+ }
break;
case SIMIX_SYNC_SYNCHRO:
}
process->waiting_synchro = NULL;
- if (!xbt_dynar_member(simix_global->process_to_run, &(process)) && process != SIMIX_process_self())
- xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
}
void simcall_HANDLER_process_killall(smx_simcall_t simcall, int reset_pid) {
/* keep the bound value of the cpu action of the VM. */
double old_bound = p_action->getBound();
if (old_bound != 0) {
- XBT_INFO("migrate VM(%s): set bound (%f) at %s", vm_name, old_bound, pm_name_dst);
+ XBT_DEBUG("migrate VM(%s): set bound (%f) at %s", vm_name, old_bound, pm_name_dst);
new_cpu_action->setBound(old_bound);
}
test = 5;
if (xbt_dynar_search_or_negative(tests, &test)!=-1){
XBT_INFO("Test 5 (turn off dest during a communication : Create a Process/task to make a communication between Tremblay and Jupiter and turn off Jupiter during the communication");
+ XBT_INFO("Warning! I think this test is completely broken and it was revealed by exception/exception test.");
+ XBT_INFO("At time 20, Jupiter should wake up with a HOST_FAILURE and it gets a TRANSFERT_FAILURE. This is because when turning off Jupiter, its processes are killed, which cancels/destroys the corresponding surf communication instead of canceling a src_ or dst_timeout.");
MSG_host_on(jupiter);
MSG_process_sleep(10);
argvF = xbt_new(char*, 2);
MSG_process_sleep(10);
XBT_INFO(" Turn Jupiter off");
MSG_host_off(jupiter);
- XBT_INFO("Test 4 seems ok, cool !(number of Process : %d, it should be 2", MSG_process_get_number());
+ XBT_INFO("Test 5 seems ok, cool !(number of Process : %d, it should be 2", MSG_process_get_number());
}
test =6;
> [Tremblay:commTX:(3) 10.000000] [msg_test/INFO] Start TX
> [Tremblay:test_launcher:(1) 10.000000] [msg_test/INFO] number of processes: 3
> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Turn Jupiter off
-> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Test 4 seems ok, cool !(number of Process : 2, it should be 2
+> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Test 5 seems ok, cool !(number of Process : 2, it should be 2
> [Tremblay:test_launcher:(1) 20.000000] [msg_test/INFO] Test done. See you!
> [Tremblay:commTX:(3) 40.000000] [msg_test/INFO] TX done
> [40.000000] [msg_test/INFO] Simulation time 40
> [Jupiter:slave:(2) 0.993652] [msg_test/INFO] Handling task "cancel"
> [Jupiter:worker1:(3) 0.993652] [msg_test/INFO] Start cancel
> [Jupiter:slave:(2) 1.093652] [msg_test/INFO] Canceling task "cancel"
-> [Jupiter:worker1:(3) 1.112666] [msg_test/INFO] Task failed
+> [Jupiter:worker1:(3) 1.093652] [msg_test/INFO] Task failed
> [Tremblay:master:(1) 1.262806] [msg_test/INFO] Goodbye now!
> [Jupiter:slave:(2) 1.262806] [msg_test/INFO] Handling task "finalize"
> [Jupiter:slave:(2) 1.262806] [msg_test/INFO] Destroying task "finalize"