More threads created than expected

You can find the program here

I am creating a program as part of 0MQ messaging. I am trying to implement what I posted in here

The program is compiled with g++ -std=c++11 test.cpp -o test -lzmq -lpthread

.

To run the program, pass one parameter as the thread number you would like to have. This parameter is then assigned to a variable worker_num

.

On the main thread, I set up the thread with

  vector<thread> pool;
  for(int i = 0; i < worker_num; i++)
  {
    cout << "main() : creating thread, " << i << endl;
    pool.push_back(thread(task1, (void *)&context, i));
  }

      

I would like to make sure that all worker threads are successfully connected to the main thread before the main thread distributes jobs to them.

  while(true)
  {
    if(sync_done)
    {
      cout << "sync done in main thread" << endl;
      break;
    }

    zmq::message_t sync_msg(4);
    memcpy((void *)sync_msg.data(), SYNC_MSG, SYNC_MSGLEN);
    for(int i = 0; i < worker_num; i++)
      distask_socket.send(sync_msg);

    for(int i = 0; i < worker_num; i++)
    {
      if(sync_done)
        break;
      if(i != 0)
        this_thread::sleep_for(chrono::milliseconds(500));

      zmq::message_t res_msg;
      int ret = getres_socket.recv(&res_msg, ZMQ_DONTWAIT);

      if(ret == -1 && errno == EAGAIN)
        continue;

      int threadID = stoi(string((char *)res_msg.data()));
      sync_done = if_sync_done(threadID, sync_array, worker_num);
    }
  }

      

So what does the main thread do: pushing #worker_num from sync

msgs with a PUSH endpoint to the worker threads every time, and then reads the msg acknowledgment from its PULL endpoint. If the main thread retrieves #worker_num from the confirmation messages, then synchronization is performed. Sync msg format from worker: this is the id of the worker thread in a string Thus, thread 0 would pass 0

in a string back to the main thread.

But running the program I have:

$ ./test 1
main() : creating thread, 0
thread id:0
thread 0 receives: sync
thread 0 sends: 0
thread 0 sync done
main thread receives sync msg from thread 1 # you may get many copies of this msg
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
Aborted

      

main thread receives sync msg from thread 1

means the thread is 2 threads created: thread 0 and thread 1. Any idea why? I passed it 1

as a parameter. It is noted that if you run the program yourself, you may get other outputs.

UPDATE:

The program has been updated: here .

Finally I realized what had happened.

the expected output, you can see that thread 0 is passing a 0

to the main thread to notify the synchronization done:

$ ./test 1
input parameter is: 1
main() : creating thread, 0
thread 0 receives: sync
to_string 0
thread 0 sends: 0, with size: 1
thread 0 sync done
pass 0 to if_sync_done
main thread receives sync msg from thread 0
sync done in main thread

      

unexpected output, you see the unprintable char being passed : stoi()

$ ./test 1
input parameter is: 1
main() : creating thread, 0
thread 0 receives: sync
to_string 0
thread 0 sends: 0, with size: 1
thread 0 sync done
pass  to if_sync_done  # !!!!!
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
Aborted

      

So it seems like I'm using it wrong message_t

. So I have to make sure that the stoi()

buffer still exists before the main thread goes through the content .

I'll add the answer myself.

+3


source to share


1 answer


zmq::message_t msg_back((void *)to_string(id).c_str(), to_string(id).size() + 1, NULL);

      

zmq::message_t

the constructor you are using does not create a copy of the buffer if [1] and [2] . Instead, it takes responsibility for the buffer.



However, you are passing a temp-driven buffer; this buffer is destroyed as soon as the constructor returns. You have msg_back

a dangling pointer stored. Any attempt to use this pointer - for example, trying to read a message on the receiving end - shows undefined behavior.

+2


source







All Articles