I've been having this problem the past couple of days: whenever I try to debug a program of mine I get an assert fail on a socket address.
There are a few curious facts about this problem:

-the program works perfectly when run normally
-the problem appears if the very same lines are in a child thread to which a pointer to the context is passed if the same lines are moved inside the main thread, no assert error on debugging -the assert is apparently triggered by a correct address in an epgm subscriber

I wrote the simplest use case I could devise

/*
 * File:   main.cpp
 * Author: erupter
 *
 * Created on January 9, 2013, 2:03 PM
 */

/*
 * File:   main.cpp
 * Author: erupter
 *
 * Created on January 9, 2013, 2:03 PM
 */

#include <cstdlib>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <list>
#include <zmqcpp.h>
#define THREAD_CONTROL_IPC      "ipc://saetta_th_control"
#define MULTICAST_ADDRESS       "239.192.1.1"
#define MULTICAST_PORT          5678
#define ROUTER_PORT             5679
#define HEADER_CTRL             "CTRL"
#define HEADER_SERVER_INFO      "SERVER_INFO"

using namespace std;
std::string _local_ip_address;
std::stringstream ss;
// custom struct to hold parameters to pass to child threads
struct parameters{
    // pointer to context
    Zmqcpp::Context * zmqcont;
    // function pointer for callbacks
    void (*callback) (std::string);
    //ip string to connect to
    std::string ip;
    //if child should bind or connect
    int conntype;
    //topics to subscribe
    std::list<std::string> topics;
};

//child thread
void *th_subscriber (void * params);
//callback
void server_location_callback(std::string ip);
//service function to get the specified interface's address
static inline bool get_iface_address(std::string interf);
/*
 *
 */
int main(int argc, char** argv) {

    struct parameters myparams;
    printf( "Requested interface wlan0, attempting to fetch address...\n");
    if (!get_iface_address("wlan0"))
        return (EXIT_FAILURE);

//create the pgm address chaining various parameters defined above plus the local ip address of the interface ss << "epgm://" << _local_ip_address << ";" << MULTICAST_ADDRESS << ":" << MULTICAST_PORT << std::endl;

    //create context
    Zmqcpp::Context* mycontext = new Zmqcpp::Context(1);

    //fill the parameters structure
    myparams.ip = ss.str();
    ss.str("");
    ss.str(HEADER_SERVER_INFO);
    myparams.topics.insert(myparams.topics.end(),ss.str());
    myparams.conntype = ZMQCPP_CONNECT;
    myparams.zmqcont=mycontext;
    myparams.callback=&server_location_callback;

    //create the connection string for the control socket
    ss.str("");
    ss << THREAD_CONTROL_IPC;
    //create the control socket
Zmqcpp::Publisher *ctrlpublisher = new Zmqcpp::Publisher(mycontext, THREAD_CONTROL_IPC, ZMQCPP_BIND);

    //create the child thread
    pthread_t th_hndl_subber;
pthread_create(&th_hndl_subber, NULL, th_subscriber, (void *)&myparams);


    while(1)
    {
        //send control messages over the control socket
        ctrlpublisher->PubMsg(2,HEADER_CTRL,"Test");
        sleep(1);
    }


    //garbage collection
    void *status;
    pthread_join(th_hndl_subber, &status);
    printf("Main thread cleaning.\n");
    ctrlpublisher->~Publisher();
    mycontext->~Context();
    printf("Main thread cleaned succesfully.");
    return (EXIT_SUCCESS);
}

static inline bool get_iface_address(std::string interf)
{
    int s;
    struct ifreq ifr = {};
    s = socket(PF_INET, SOCK_DGRAM, 0);

    strncpy(ifr.ifr_name, interf.c_str(), sizeof(ifr.ifr_name));

    if (ioctl(s, SIOCGIFADDR, &ifr) >= 0)
    {
_local_ip_address = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr); printf("Detected interface IP address is %s.\nCreating sockets on this address.\n", _local_ip_address.c_str());
        return true;
    }
printf("Unable to get interface IP address: is the interface configured?\n");
    return false;

}

void *th_subscriber (void * params)
{
    //declare some service variables
    int th_continue=1;
    std::string server_ip;
    std::stringstream ss;
    std::string msgtype;
    std::string msgmaster = HEADER_SERVER_INFO;
    std::string temp;

    //recast the pointer to the parameter structure
    struct parameters *myparams = (struct parameters *) params;

    //create the subscriber for the real messages we would like to get
    // THIS IS WHAT TRIGGERS THE ASSERT DURING DEBUG
Zmqcpp::Subscriber *msgsubber = new Zmqcpp::Subscriber(myparams->zmqcont,&(myparams->ip), myparams->conntype);

    //have it subscribe to each topic we are told to
for (std::list<std::string>::iterator it = myparams->topics.begin(); it != myparams->topics.end(); it++)
    {
        cout << "Subscribing to <" << *it <<">"<<std::endl;
        printf("Subscribing to: <%s>\n",it->c_str());
        msgsubber->SubscribeTopic(*it);
    }


    ss.str("");
    ss << THREAD_CONTROL_IPC;

//create the control subscriber over the specified ipc control address and subscribe it Zmqcpp::Subscriber *ctrlsubber = new Zmqcpp::Subscriber(myparams->zmqcont,THREAD_CONTROL_IPC, ZMQCPP_CONNECT);
    ctrlsubber->SubscribeTopic(HEADER_CTRL);

    sleep(1);
    while(th_continue==1)
    {

        //do something silly with the control messages
        ss.str("");
        ss << ctrlsubber->RecvMsg();
        msgtype.clear();
        msgtype = ss.str();
        if (!msgtype.compare(HEADER_CTRL))
        {
            ss.str("");
            ss << "Control message: " << ctrlsubber->RecvMsg();
            temp.clear();
            temp.assign(ss.str());
            myparams->callback(temp.c_str());
            if (temp.compare("Control message: KILL")==0)
                th_continue=0;

        }
    }
    //child thread garbage collection
    printf("Child thread cleaning resources.\n");
    ctrlsubber->~Subscriber();
    //msgsubber->~Subscriber();
    printf("Child thread terminating.\n");
    return(EXIT_SUCCESS);

}

void server_location_callback(std::string ip)
{

    cout << ip.c_str() <<  std::endl;
}


but nevertheless you would need my library to execute the code (https://github.com/erupter/saettang). This clearly displays the problem: it runs correctly, but gives the assert error when attempting to debug.
Invalid argument (session_base.cpp:490)

If you comment out lines 123 to 129 you can debug the application without problems.
With those lines you can't debug, but you can run it and it works.

Appreciate any help.
Thank you
Claudio
_______________________________________________
zeromq-dev mailing list
[email protected]
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to