Use dedicated variables to control shutdown of parallel threads like keypress and...
[hashcat.git] / src / hashcat.c
index a82155a..1effe6a 100644 (file)
@@ -1,4 +1,4 @@
- /**
+/**
  * Authors.....: Jens Steube <jens.steube@gmail.com>
  *               Gabriele Gristina <matrix@hashcat.net>
  *               magnum <john.magnum@hushmail.com>
@@ -78,7 +78,7 @@ double TARGET_MS_PROFILE[4]     = { 2, 12, 96, 480 };
 #define NVIDIA_SPIN_DAMP        100
 #define GPU_TEMP_DISABLE        0
 #define GPU_TEMP_ABORT          90
-#define GPU_TEMP_RETAIN         65
+#define GPU_TEMP_RETAIN         75
 #define WORKLOAD_PROFILE        2
 #define KERNEL_ACCEL            0
 #define KERNEL_LOOPS            0
@@ -932,7 +932,6 @@ void status_display ()
 {
   if (data.devices_status == STATUS_INIT)     return;
   if (data.devices_status == STATUS_STARTING) return;
-  if (data.devices_status == STATUS_BYPASS)   return;
 
   if (data.machine_readable == 1)
   {
@@ -1691,7 +1690,6 @@ static void status_benchmark ()
 {
   if (data.devices_status == STATUS_INIT)     return;
   if (data.devices_status == STATUS_STARTING) return;
-  if (data.devices_status == STATUS_BYPASS)   return;
 
   if (data.machine_readable == 1)
   {
@@ -3047,6 +3045,7 @@ static void choose_kernel (hc_device_param_t *device_param, const uint attack_ex
       if (data.devices_status == STATUS_CRACKED) break;
       if (data.devices_status == STATUS_ABORTED) break;
       if (data.devices_status == STATUS_QUIT)    break;
+      if (data.devices_status == STATUS_BYPASS)  break;
 
       /**
        * speed
@@ -3703,6 +3702,7 @@ static void run_cracker (hc_device_param_t *device_param, const uint pws_cnt)
       if (data.devices_status == STATUS_CRACKED) break;
       if (data.devices_status == STATUS_ABORTED) break;
       if (data.devices_status == STATUS_QUIT)    break;
+      if (data.devices_status == STATUS_BYPASS)  break;
 
       /**
        * result
@@ -4165,7 +4165,7 @@ static void *thread_monitor (void *p)
     return (p);
   }
 
-  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+  while (data.shutdown_inner == 0)
   {
     hc_sleep (sleep_time);
 
@@ -4351,7 +4351,7 @@ static void *thread_monitor (void *p)
 
       time (&runtime_cur);
 
-      int runtime_left = data.runtime_start + data.runtime - runtime_cur;
+      int runtime_left = data.proc_start + data.runtime - runtime_cur;
 
       if (runtime_left <= 0)
       {
@@ -4387,7 +4387,7 @@ static void *thread_monitor (void *p)
 
       if (status_left == 0)
       {
-        //hc_thread_mutex_lock (mux_display);
+        hc_thread_mutex_lock (mux_display);
 
         if (data.quiet == 0) clear_prompt ();
 
@@ -4397,7 +4397,7 @@ static void *thread_monitor (void *p)
 
         if (data.quiet == 0) log_info ("");
 
-        //hc_thread_mutex_unlock (mux_display);
+        hc_thread_mutex_unlock (mux_display);
 
         status_left = data.status_timer;
       }
@@ -4454,7 +4454,7 @@ static void *thread_outfile_remove (void *p)
 
   uint check_left = outfile_check_timer; // or 1 if we want to check it at startup
 
-  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+  while (data.shutdown_inner == 0)
   {
     hc_sleep (1);
 
@@ -4782,7 +4782,7 @@ static uint get_work (hc_device_param_t *device_param, const u64 max)
   hc_thread_mutex_lock (mux_dispatcher);
 
   const u64 words_cur  = data.words_cur;
-  const u64 words_base = (data.limit == 0) ? data.words_base : data.limit;
+  const u64 words_base = (data.limit == 0) ? data.words_base : MIN (data.limit, data.words_base);
 
   device_param->words_off = words_cur;
 
@@ -4832,7 +4832,7 @@ static void *thread_calc_stdin (void *p)
 
   const uint attack_kern = data.attack_kern;
 
-  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+  while ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
   {
     hc_thread_mutex_lock (mux_dispatcher);
 
@@ -4960,7 +4960,7 @@ static void *thread_calc (void *p)
 
   if (attack_mode == ATTACK_MODE_BF)
   {
-    while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+    while ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
     {
       const uint work = get_work (device_param, -1);
 
@@ -5072,7 +5072,7 @@ static void *thread_calc (void *p)
 
     u64 words_cur = 0;
 
-    while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+    while ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
     {
       u64 words_off = 0;
       u64 words_fin = 0;
@@ -7360,17 +7360,19 @@ int main (int argc, char **argv)
     data.status = status;
   }
 
-  uint i_threads_cnt = 0;
+  uint outer_threads_cnt = 0;
 
-  hc_thread_t *i_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
+  hc_thread_t *outer_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
+
+  data.shutdown_outer = 0;
 
   if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
   {
     if ((data.wordlist_mode == WL_MODE_FILE) || (data.wordlist_mode == WL_MODE_MASK))
     {
-      hc_thread_create (i_threads[i_threads_cnt], thread_keypress, NULL);
+      hc_thread_create (outer_threads[outer_threads_cnt], thread_keypress, NULL);
 
-      i_threads_cnt++;
+      outer_threads_cnt++;
     }
   }
 
@@ -13536,7 +13538,7 @@ int main (int argc, char **argv)
 
         if (cpu_rule_to_kernel_rule (rule_buf, rule_len, &kernel_rules_buf[kernel_rules_cnt]) == -1)
         {
-          log_info ("WARNING: Cannot convert rule for use on device in file %s on line %u: %s", rp_file, rule_line, rule_buf);
+          log_info ("WARNING: Cannot convert rule for use on OpenCL device in file %s on line %u: %s", rp_file, rule_line, rule_buf);
 
           memset (&kernel_rules_buf[kernel_rules_cnt], 0, sizeof (kernel_rule_t)); // needs to be cleared otherwise we could have some remaining data
 
@@ -13546,7 +13548,7 @@ int main (int argc, char **argv)
         /* its so slow
         if (rulefind (&kernel_rules_buf[kernel_rules_cnt], kernel_rules_buf, kernel_rules_cnt, sizeof (kernel_rule_t), sort_by_kernel_rule))
         {
-          log_info ("Duplicate rule for use on device in file %s in line %u: %s", rp_file, rule_line, rule_buf);
+          log_info ("Duplicate rule for use on OpenCL device in file %s in line %u: %s", rp_file, rule_line, rule_buf);
 
           continue;
         }
@@ -13650,7 +13652,7 @@ int main (int argc, char **argv)
      * generate NOP rules
      */
 
-    if (kernel_rules_cnt == 0)
+    if ((rp_files_cnt == 0) && (rp_gen == 0))
     {
       kernel_rules_buf = (kernel_rule_t *) mymalloc (sizeof (kernel_rule_t));
 
@@ -13662,6 +13664,13 @@ int main (int argc, char **argv)
     data.kernel_rules_cnt = kernel_rules_cnt;
     data.kernel_rules_buf = kernel_rules_buf;
 
+    if (kernel_rules_cnt == 0)
+    {
+      log_error ("ERROR: No valid rules left");
+
+      return (-1);
+    }
+
     /**
      * OpenCL platforms: detect
      */
@@ -14179,7 +14188,7 @@ int main (int argc, char **argv)
 
         device_param->device_name_chksum = device_name_chksum;
 
-        // device_processor_cores
+        // vendor specific
 
         if (device_param->device_type & CL_DEVICE_TYPE_GPU)
         {
@@ -14202,28 +14211,9 @@ int main (int argc, char **argv)
           }
         }
 
-        // device_processor_cores
-
-        if (device_type & CL_DEVICE_TYPE_CPU)
-        {
-          cl_uint device_processor_cores = 1;
-
-          device_param->device_processor_cores = device_processor_cores;
-        }
-
         if (device_type & CL_DEVICE_TYPE_GPU)
         {
-          if (device_vendor_id == VENDOR_ID_AMD)
-          {
-            cl_uint device_processor_cores = 0;
-
-            #define CL_DEVICE_WAVEFRONT_WIDTH_AMD               0x4043
-
-            hc_clGetDeviceInfo (data.ocl, device_param->device, CL_DEVICE_WAVEFRONT_WIDTH_AMD, sizeof (device_processor_cores), &device_processor_cores, NULL);
-
-            device_param->device_processor_cores = device_processor_cores;
-          }
-          else if (device_vendor_id == VENDOR_ID_NV)
+          if (device_vendor_id == VENDOR_ID_NV)
           {
             cl_uint kernel_exec_timeout = 0;
 
@@ -14233,14 +14223,6 @@ int main (int argc, char **argv)
 
             device_param->kernel_exec_timeout = kernel_exec_timeout;
 
-            cl_uint device_processor_cores = 0;
-
-            #define CL_DEVICE_WARP_SIZE_NV                      0x4003
-
-            hc_clGetDeviceInfo (data.ocl, device_param->device, CL_DEVICE_WARP_SIZE_NV, sizeof (device_processor_cores), &device_processor_cores, NULL);
-
-            device_param->device_processor_cores = device_processor_cores;
-
             cl_uint sm_minor = 0;
             cl_uint sm_major = 0;
 
@@ -14276,12 +14258,6 @@ int main (int argc, char **argv)
 
             device_param->nvidia_spin_damp /= 100;
           }
-          else
-          {
-            cl_uint device_processor_cores = 1;
-
-            device_param->device_processor_cores = device_processor_cores;
-          }
         }
 
         // display results
@@ -14539,9 +14515,9 @@ int main (int argc, char **argv)
 
             if (hm_NVML_nvmlDeviceGetFanSpeed (data.hm_nvml, 0, hm_adapters_nvml[i].nvml, &speed) == NVML_SUCCESS) hm_adapters_nvml[i].fan_get_supported = 1;
 
-            hm_NVML_nvmlDeviceSetComputeMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_COMPUTEMODE_EXCLUSIVE_PROCESS);
-
-            hm_NVML_nvmlDeviceSetGpuOperationMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_GOM_ALL_ON);
+            // doesn't seem to create any advantages
+            //hm_NVML_nvmlDeviceSetComputeMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_COMPUTEMODE_EXCLUSIVE_PROCESS);
+            //hm_NVML_nvmlDeviceSetGpuOperationMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_GOM_ALL_ON);
           }
         }
       }
@@ -14648,9 +14624,6 @@ int main (int argc, char **argv)
      * OpenCL devices: allocate buffer for device specific information
      */
 
-    int *temp_retain_fanspeed_value  = (int *) mycalloc (data.devices_cnt, sizeof (int));
-    int *temp_retain_fanpolicy_value = (int *) mycalloc (data.devices_cnt, sizeof (int));
-
     ADLOD6MemClockState *od_clock_mem_status = (ADLOD6MemClockState *) mycalloc (data.devices_cnt, sizeof (ADLOD6MemClockState));
 
     int *od_power_control_status = (int *) mycalloc (data.devices_cnt, sizeof (int));
@@ -15013,7 +14986,6 @@ int main (int argc, char **argv)
 
       const char *device_name_chksum      = device_param->device_name_chksum;
       const u32   device_processors       = device_param->device_processors;
-      const u32   device_processor_cores  = device_param->device_processor_cores;
 
       /**
        * create context for each device
@@ -15047,7 +15019,9 @@ int main (int argc, char **argv)
       if (hash_mode ==  3000) kernel_threads = 64; // DES
       if (hash_mode ==  3200) kernel_threads = 8;  // Blowfish
       if (hash_mode ==  7500) kernel_threads = 64; // RC4
+      if (hash_mode ==  8900) kernel_threads = 32; // scrypt
       if (hash_mode ==  9000) kernel_threads = 8;  // Blowfish
+      if (hash_mode ==  9300) kernel_threads = 32; // scrypt
       if (hash_mode ==  9700) kernel_threads = 64; // RC4
       if (hash_mode ==  9710) kernel_threads = 64; // RC4
       if (hash_mode ==  9800) kernel_threads = 64; // RC4
@@ -15134,6 +15108,9 @@ int main (int argc, char **argv)
           }
         }
 
+        device_param->kernel_accel_min = 1;
+        device_param->kernel_accel_max = 8;
+
         for (uint tmto = tmto_start; tmto < tmto_stop; tmto++)
         {
           // TODO: in theory the following calculation needs to be done per salt, not global
@@ -15143,7 +15120,7 @@ int main (int argc, char **argv)
 
           size_scryptV /= 1 << tmto;
 
-          size_scryptV *= device_processors * device_processor_cores;
+          size_scryptV *= device_param->device_processors * device_param->kernel_threads * device_param->kernel_accel_max;
 
           if (size_scryptV > device_param->device_maxmem_alloc)
           {
@@ -15155,7 +15132,7 @@ int main (int argc, char **argv)
           for (uint salts_pos = 0; salts_pos < data.salts_cnt; salts_pos++)
           {
             data.salts_buf[salts_pos].scrypt_tmto = tmto;
-            data.salts_buf[salts_pos].scrypt_phy  = device_processors * device_processor_cores;
+            data.salts_buf[salts_pos].scrypt_phy  = device_param->device_processors * device_param->kernel_threads * device_param->kernel_accel_max;
           }
 
           break;
@@ -15485,7 +15462,7 @@ int main (int argc, char **argv)
 
       char build_opts_new[1024] = { 0 };
 
-      snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -D VENDOR_ID=%u -D CUDA_ARCH=%d -D VECT_SIZE=%u -D DEVICE_TYPE=%u -D KERN_TYPE=%u -D _unroll -cl-std=CL1.1", build_opts, device_param->device_vendor_id, (device_param->sm_major * 100) + device_param->sm_minor, device_param->vector_width, (u32) device_param->device_type, kern_type);
+      snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -D VENDOR_ID=%u -D CUDA_ARCH=%d -D VECT_SIZE=%u -D DEVICE_TYPE=%u -D DGST_R0=%u -D DGST_R1=%u -D DGST_R2=%u -D DGST_R3=%u -D DGST_ELEM=%u -D KERN_TYPE=%u -D _unroll -cl-std=CL1.1", build_opts, device_param->device_vendor_id, (device_param->sm_major * 100) + device_param->sm_minor, device_param->vector_width, (u32) device_param->device_type, data.dgst_pos0, data.dgst_pos1, data.dgst_pos2, data.dgst_pos3, data.dgst_size / 4, kern_type);
 
       strncpy (build_opts, build_opts_new, sizeof (build_opts));
 
@@ -16314,9 +16291,6 @@ int main (int argc, char **argv)
             const int fanspeed  = hm_get_fanspeed_with_device_id  (device_id);
             const int fanpolicy = hm_get_fanpolicy_with_device_id (device_id);
 
-            temp_retain_fanspeed_value[device_id]  = fanspeed;
-            temp_retain_fanpolicy_value[device_id] = fanpolicy;
-
             // we also set it to tell the OS we take control over the fan and it's automatic controller
             // if it was set to automatic. we do not control user-defined fanspeeds.
 
@@ -17229,21 +17203,16 @@ int main (int argc, char **argv)
      * status and monitor threads
      */
 
-    if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+    if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
     {
       data.devices_status = STATUS_STARTING;
     }
 
-    uint ni_threads_cnt = 0;
-
-    hc_thread_t *ni_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
+    uint inner_threads_cnt = 0;
 
-    if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
-    {
-      hc_thread_create (ni_threads[ni_threads_cnt], thread_monitor, NULL);
+    hc_thread_t *inner_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
 
-      ni_threads_cnt++;
-    }
+    data.shutdown_inner = 0;
 
     /**
       * Outfile remove
@@ -17251,6 +17220,10 @@ int main (int argc, char **argv)
 
     if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
     {
+      hc_thread_create (inner_threads[inner_threads_cnt], thread_monitor, NULL);
+
+      inner_threads_cnt++;
+
       if (outfile_check_timer != 0)
       {
         if (data.outfile_check_directory != NULL)
@@ -17260,9 +17233,9 @@ int main (int argc, char **argv)
               !((hash_mode >= 13700) && (hash_mode <= 13799)) &&
               (hash_mode != 9000))
           {
-            hc_thread_create (ni_threads[ni_threads_cnt], thread_outfile_remove, NULL);
+            hc_thread_create (inner_threads[inner_threads_cnt], thread_outfile_remove, NULL);
 
-            ni_threads_cnt++;
+            inner_threads_cnt++;
           }
           else
           {
@@ -17308,6 +17281,10 @@ int main (int argc, char **argv)
 
     for (uint maskpos = rd->maskpos; maskpos < maskcnt; maskpos++)
     {
+      if (data.devices_status == STATUS_CRACKED) continue;
+      if (data.devices_status == STATUS_ABORTED) continue;
+      if (data.devices_status == STATUS_QUIT)    continue;
+
       if (maskpos > rd->maskpos)
       {
         rd->dictpos = 0;
@@ -17545,15 +17522,21 @@ int main (int argc, char **argv)
         }
       }
 
-      for (uint dictpos = rd->dictpos; dictpos < dictcnt; )
+      for (uint dictpos = rd->dictpos; dictpos < dictcnt; dictpos++)
       {
+        if (data.devices_status == STATUS_CRACKED) continue;
+        if (data.devices_status == STATUS_ABORTED) continue;
+        if (data.devices_status == STATUS_QUIT)    continue;
+
+        rd->dictpos = dictpos;
+
         char *subid = logfile_generate_subid ();
 
         data.subid = subid;
 
         logfile_sub_msg ("START");
 
-        if (data.devices_status == STATUS_STARTING)
+        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
         {
           data.devices_status = STATUS_INIT;
         }
@@ -17656,7 +17639,7 @@ int main (int argc, char **argv)
 
             if (data.words_cnt == 0)
             {
-              dictpos++;
+              logfile_sub_msg ("STOP");
 
               continue;
             }
@@ -17703,7 +17686,7 @@ int main (int argc, char **argv)
 
           if (data.words_cnt == 0)
           {
-            dictpos++;
+            logfile_sub_msg ("STOP");
 
             continue;
           }
@@ -17743,7 +17726,7 @@ int main (int argc, char **argv)
 
           if (data.words_cnt == 0)
           {
-            dictpos++;
+            logfile_sub_msg ("STOP");
 
             continue;
           }
@@ -17807,10 +17790,6 @@ int main (int argc, char **argv)
 
             // skip to next mask
 
-            dictpos++;
-
-            rd->dictpos = dictpos;
-
             logfile_sub_msg ("STOP");
 
             continue;
@@ -18088,16 +18067,16 @@ int main (int argc, char **argv)
 
         hc_thread_t *c_threads = (hc_thread_t *) mycalloc (data.devices_cnt, sizeof (hc_thread_t));
 
-        if (data.devices_status == STATUS_INIT)
+        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
         {
           data.devices_status = STATUS_AUTOTUNE;
+        }
 
-          for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
-          {
-            hc_device_param_t *device_param = &devices_param[device_id];
+        for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
+        {
+          hc_device_param_t *device_param = &devices_param[device_id];
 
-            hc_thread_create (c_threads[device_id], thread_autotune, device_param);
-          }
+          hc_thread_create (c_threads[device_id], thread_autotune, device_param);
         }
 
         hc_thread_wait (data.devices_cnt, c_threads);
@@ -18145,7 +18124,7 @@ int main (int argc, char **argv)
          * create cracker threads
          */
 
-        if (data.devices_status == STATUS_AUTOTUNE)
+        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
         {
           data.devices_status = STATUS_RUNNING;
         }
@@ -18179,20 +18158,17 @@ int main (int argc, char **argv)
 
         data.runtime_start = runtime_start;
 
-        if (data.devices_status == STATUS_RUNNING)
+        for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
         {
-          for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
-          {
-            hc_device_param_t *device_param = &devices_param[device_id];
+          hc_device_param_t *device_param = &devices_param[device_id];
 
-            if (wordlist_mode == WL_MODE_STDIN)
-            {
-              hc_thread_create (c_threads[device_id], thread_calc_stdin, device_param);
-            }
-            else
-            {
-              hc_thread_create (c_threads[device_id], thread_calc, device_param);
-            }
+          if (wordlist_mode == WL_MODE_STDIN)
+          {
+            hc_thread_create (c_threads[device_id], thread_calc_stdin, device_param);
+          }
+          else
+          {
+            hc_thread_create (c_threads[device_id], thread_calc, device_param);
           }
         }
 
@@ -18200,6 +18176,11 @@ int main (int argc, char **argv)
 
         local_free (c_threads);
 
+        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
+        {
+          data.devices_status = STATUS_EXHAUSTED;
+        }
+
         logfile_sub_var_uint ("status-after-work", data.devices_status);
 
         data.restore = 0;
@@ -18218,47 +18199,34 @@ int main (int argc, char **argv)
           induction_dictionaries_cnt = count_dictionaries (induction_dictionaries);
         }
 
-        if (benchmark == 0)
+        if (benchmark == 1)
         {
-          if (((dictpos + 1) < dictcnt) || ((maskpos + 1) < maskcnt) || induction_dictionaries_cnt)
-          {
-            if (quiet == 0) clear_prompt ();
+          status_benchmark ();
 
-            if (quiet == 0) log_info ("");
-
-            if (status == 1)
-            {
-              status_display ();
-            }
-            else
-            {
-              if (quiet == 0) status_display ();
-            }
-
-            if (quiet == 0) log_info ("");
+          if (machine_readable == 0)
+          {
+            log_info ("");
           }
         }
-
-        if (attack_mode == ATTACK_MODE_BF)
-        {
-          dictpos++;
-
-          rd->dictpos = dictpos;
-        }
         else
         {
-          if (induction_dictionaries_cnt)
+          if (quiet == 0)
           {
-            qsort (induction_dictionaries, induction_dictionaries_cnt, sizeof (char *), sort_by_mtime);
-          }
-          else
-          {
-            dictpos++;
+            clear_prompt ();
+
+            log_info ("");
+
+            if (stdout_flag == 0) status_display ();
 
-            rd->dictpos = dictpos;
+            log_info ("");
           }
         }
 
+        if (induction_dictionaries_cnt)
+        {
+          qsort (induction_dictionaries, induction_dictionaries_cnt, sizeof (char *), sort_by_mtime);
+        }
+
         time_t runtime_stop;
 
         time (&runtime_stop);
@@ -18272,34 +18240,36 @@ int main (int argc, char **argv)
 
         global_free (subid);
 
-        // finalize task
-
-        if (data.devices_status == STATUS_STOP_AT_CHECKPOINT) check_checkpoint ();
-
-        if (data.devices_status == STATUS_CRACKED) break;
-        if (data.devices_status == STATUS_ABORTED) break;
-        if (data.devices_status == STATUS_QUIT)    break;
+        // from this point we handle bypass as running
 
         if (data.devices_status == STATUS_BYPASS)
         {
           data.devices_status = STATUS_RUNNING;
         }
-      }
 
-      if (data.devices_status == STATUS_STOP_AT_CHECKPOINT) check_checkpoint ();
+        // and overwrite benchmark aborts as well
+
+        if (data.benchmark == 1)
+        {
+          if (data.devices_status == STATUS_ABORTED)
+          {
+            data.devices_status = STATUS_RUNNING;
+          }
+        }
+
+        // finalize task
+
+        if (data.devices_status == STATUS_CRACKED) break;
+        if (data.devices_status == STATUS_ABORTED) break;
+        if (data.devices_status == STATUS_QUIT)    break;
+      }
 
       if (data.devices_status == STATUS_CRACKED) break;
       if (data.devices_status == STATUS_ABORTED) break;
       if (data.devices_status == STATUS_QUIT)    break;
-
-      if (data.devices_status == STATUS_BYPASS)
-      {
-        data.devices_status = STATUS_RUNNING;
-      }
     }
 
     // problems could occur if already at startup everything was cracked (because of .pot file reading etc), we must set some variables here to avoid NULL pointers
-
     if (attack_mode == ATTACK_MODE_STRAIGHT)
     {
       if (data.wordlist_mode == WL_MODE_FILE)
@@ -18338,11 +18308,6 @@ int main (int argc, char **argv)
       }
     }
 
-    if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
-    {
-      data.devices_status = STATUS_EXHAUSTED;
-    }
-
     // if cracked / aborted remove last induction dictionary
 
     for (int file_pos = 0; file_pos < induction_dictionaries_cnt; file_pos++)
@@ -18355,14 +18320,16 @@ int main (int argc, char **argv)
       }
     }
 
-    // wait for non-interactive threads
+    // wait for inner threads
 
-    for (uint thread_idx = 0; thread_idx < ni_threads_cnt; thread_idx++)
+    data.shutdown_inner = 1;
+
+    for (uint thread_idx = 0; thread_idx < inner_threads_cnt; thread_idx++)
     {
-      hc_thread_wait (1, &ni_threads[thread_idx]);
+      hc_thread_wait (1, &inner_threads[thread_idx]);
     }
 
-    local_free (ni_threads);
+    local_free (inner_threads);
 
     // we dont need restore file anymore
     if (data.restore_disable == 0)
@@ -18389,29 +18356,6 @@ int main (int argc, char **argv)
      * Clean up
      */
 
-    if (benchmark == 1)
-    {
-      status_benchmark ();
-
-      if (machine_readable == 0)
-      {
-        log_info ("");
-      }
-    }
-    else
-    {
-      if (quiet == 0)
-      {
-        clear_prompt ();
-
-        log_info ("");
-
-        if (stdout_flag == 0) status_display ();
-
-        log_info ("");
-      }
-    }
-
     for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
     {
       hc_device_param_t *device_param = &data.devices_param[device_id];
@@ -18419,15 +18363,10 @@ int main (int argc, char **argv)
       if (device_param->skipped) continue;
 
       local_free (device_param->combs_buf);
-
       local_free (device_param->hooks_buf);
-
       local_free (device_param->device_name);
-
       local_free (device_param->device_name_chksum);
-
       local_free (device_param->device_version);
-
       local_free (device_param->driver_version);
 
       if (device_param->pws_buf)            myfree                    (device_param->pws_buf);
@@ -18485,7 +18424,7 @@ int main (int argc, char **argv)
     #ifdef HAVE_HWMON
     if (gpu_temp_disable == 0)
     {
-      if (gpu_temp_retain != 0) // VENDOR_ID_AMD is implied here
+      if (gpu_temp_retain != 0)
       {
         hc_thread_mutex_lock (mux_adl);
 
@@ -18497,30 +18436,24 @@ int main (int argc, char **argv)
 
           if (data.hm_device[device_id].fan_set_supported == 1)
           {
-            int fanspeed  = temp_retain_fanspeed_value[device_id];
-            int fanpolicy = temp_retain_fanpolicy_value[device_id];
+            int rc = -1;
 
-            if (fanpolicy == 1)
+            if (device_param->device_vendor_id == VENDOR_ID_AMD)
             {
-              int rc = -1;
-
-              if (device_param->device_vendor_id == VENDOR_ID_AMD)
-              {
-                rc = hm_set_fanspeed_with_device_id_adl (device_id, fanspeed, 0);
-              }
-              else if (device_param->device_vendor_id == VENDOR_ID_NV)
-              {
-                #ifdef LINUX
-                rc = set_fan_control (data.hm_xnvctrl, data.hm_device[device_id].xnvctrl, NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE);
-                #endif
-
-                #ifdef WIN
-                rc = hm_set_fanspeed_with_device_id_nvapi (device_id, fanspeed, fanpolicy);
-                #endif
-              }
+              rc = hm_set_fanspeed_with_device_id_adl (device_id, 100, 0);
+            }
+            else if (device_param->device_vendor_id == VENDOR_ID_NV)
+            {
+              #ifdef LINUX
+              rc = set_fan_control (data.hm_xnvctrl, data.hm_device[device_id].xnvctrl, NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE);
+              #endif
 
-              if (rc == -1) log_info ("WARNING: Failed to restore default fan speed and policy for device #%", device_id + 1);
+              #ifdef WIN
+              rc = hm_set_fanspeed_with_device_id_nvapi (device_id, 100, 0);
+              #endif
             }
+
+            if (rc == -1) log_info ("WARNING: Failed to restore default fan speed and policy for device #%", device_id + 1);
           }
         }
 
@@ -18530,7 +18463,7 @@ int main (int argc, char **argv)
 
     // reset power tuning
 
-    if (powertune_enable == 1) // VENDOR_ID_AMD is implied here
+    if (powertune_enable == 1)
     {
       hc_thread_mutex_lock (mux_adl);
 
@@ -18681,7 +18614,6 @@ int main (int argc, char **argv)
     local_free (bitmap_s2_d);
 
     #ifdef HAVE_HWMON
-    local_free (temp_retain_fanspeed_value);
     local_free (od_clock_mem_status);
     local_free (od_power_control_status);
     local_free (nvml_power_limit);
@@ -18712,14 +18644,16 @@ int main (int argc, char **argv)
     if (data.devices_status == STATUS_QUIT) break;
   }
 
-  // wait for interactive threads
+  // wait for outer threads
+
+  data.shutdown_outer = 1;
 
-  for (uint thread_idx = 0; thread_idx < i_threads_cnt; thread_idx++)
+  for (uint thread_idx = 0; thread_idx < outer_threads_cnt; thread_idx++)
   {
-    hc_thread_wait (1, &i_threads[thread_idx]);
+    hc_thread_wait (1, &outer_threads[thread_idx]);
   }
 
-  local_free (i_threads);
+  local_free (outer_threads);
 
   // destroy others mutex