title: How to avoid deadlock inside a class running by concurrent.futures
body: <p>I have a class that's doing some I/O bound tasks which I decided to make faster by using python concurrent.
  So without further talking the important code parts are (Removed the unnecessary parts):</p>
  <pre><code>class toolbox:
      def __init__(self, username, password, fid, settings):
          #...
          self.access_token     = &quot;&quot;
          self.login_data       = {
              &quot;username&quot;: username,
              &quot;password&quot;: password,
              &quot;sfid&quot;    : fid
          }
          self.request_headers  = {
              &quot;User-Agent&quot;:&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36&quot;,
              &quot;Accept&quot;:&quot;application/json, text/plain, */*&quot;,
              &quot;Authorization&quot;:&quot;&quot;
          }
          self.request_data     = {}
  
      def new_session(self, n=0):
          session = requests.Session()
          #...
              if token:
                  self.access_token = &quot;Bearer &quot;+token
                  self.request_headers[&quot;Authorization&quot;] = self.access_token
                  dreq = session.get(self.data_url, headers=self.request_headers)
                  if dreq.status_code==200:
                      self.request_data = dict( dreq.json() )
                      print(&quot;[ ALL SET! ]&quot;, flush=True)
                  else:
                      print(f&quot;\n{R}[!]{end} Something went wrong, can't grab data required to start searching!&quot;, flush=True)
                      if n!=3:
                          print(&quot;[~] Trying to relogin and grab data again!&quot;, flush=True)
                          self.new_session(n+1)
                      else:
                          input(f&quot;{R}[!]{end} Maximum tries exceed! There's another thing wrong can't find it! Quiting...&quot;)
                          sys.exit(0)
              #...
          #...
  
      def check_number(self, row):
          #...
          if not self.Cookies:
              print(f&quot;{R}[!]{end} Creating a new session for number {number}&quot;, flush=True)
              self.new_session()
  
          #...
          while True:
              try:
                  req = requests.post(
                      self.search_url,
                      headers = self.request_headers,
                      json    = self.request_data,
                      cookies = self.Cookies,
                      timeout = self.settings[&quot;request_timeout&quot;]
                  )
                  if req.status_code!=200:
                      #...
                      if n==1:
                          n=0
                          print(f&quot;{R}[!]{end} Creating a new session for number {number}&quot;, flush=True)
                          self.new_session()
                      else:
                          n+=1
                      if req.status_code!=401:
                          raise requests.exceptions.RequestException
                  #...
  
              except requests.exceptions.RequestException as e:
                  #...
  </code></pre>
  <p>So the function check_number while doing its scraping, if it got 401 status code, it will login to get a new session. That's because the API session needs to be renewed each specific period!</p>
  <p>Ok perfect, the problem comes when the threading starts and that's in the below function (in the same class):</p>
  <pre><code>def check_file(self, input_file):
          #...
  
          if self.settings[&quot;threaded&quot;]:
              #...
              with concurrent.futures.ThreadPoolExecutor(max_workers=self.settings[&quot;threads&quot;]) as executor:
                  #...
                  for num in executor.map(
                          self.check_number, manager.data_rows,
                          timeout=self.settings[&quot;running_timeout&quot;],
                          chunksize=self.settings[&quot;save_interval&quot;] ):
                      if not self.Cookies:
                          self.new_session()
                      if num:
                          #...
                      time.sleep(self.settings[&quot;throttle&quot;])
          else:
              start_time = time.time()
              for row in manager.data_rows:
                  #...
          #...
  </code></pre>
  <p>The program will run smoothly without any problem till the session ends, all the threads will try to renew the session at the same time which will do a deadlock ofc. So the question is how could I refactor the code so when the session ends I can renew the session for all threads at once without causing a deadlock? Also notice that in this program the user can decide to run unthreaded using settings as you notice the &quot;else&quot; statement.</p>
  <p>I searched and tried a lot of things but I'm not very good with threading, I hope anyone could help me as this is a problem in my job, not a side project.</p>
  <p>Thanks in advance</p>