GTK - pango-critical error when disabling entry field

928 Views Asked by At

I am encountering the following error (twice) when I try to disable an entry field:

(SDS-CW:7145): Pango-CRITICAL **: 16:38:37.521: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed

(SDS-CW:7145): Pango-CRITICAL **: 16:38:37.521: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed

The idea is to take an IP Address from an entry field into the program. This all worked perfectly until I started trying to validate the entry was a valid IP Address however. It used to disable the field as soon as the submit button was pressed to prevent the user changing the entered text, however now the field blanks and seems to break, as shown below.

enter image description here

When the entry field is not disabled, I do not get the errors.

However, the validate function seems to run fine, and the check function wait_for_connction() (being run in a new thread) starts running, but consistently after 1 iteration of the function the pango error is thrown.

Here is the full console output when I enter 192.168.0.254 in the entry field:

/home/csc/CLionProjects/SDS-CW/GUIs/Server/cmake-build-debug/SDS-CW
Valid IP
Selected Server IP: xxx.xxx.xxx.xxx
Checking server...

(SDS-CW:7423): Pango-CRITICAL **: 16:57:11.582: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed

(SDS-CW:7423): Pango-CRITICAL **: 16:57:11.582: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed
Checking server...
Checking server...
Checking server...
Checking server...
Connected to: xxx.xxx.xxx.xxx
Conn success

Interestingly, I also seem to get the errors again every time the GTK window loses focus and then again when it regains focus.

Here is the callback for the button:

int connect_server(GtkButton *button, gpointer user_data) {

    struct data *server_data = (struct data*)user_data;

    GtkWidget *serverIPEntry = server_data->serverIPEntry;
    GtkWidget *sererPortEntry = server_data->serverPortEntry;
    GtkWidget *connectButton = server_data->connectButton;
    GtkWidget *serverIPErrorLabel = server_data->serverIPErrorLabel;
    GtkWidget *serverPortErrorLabel = server_data->serverPortErrorLabel;

    char* serverIP = (char*)gtk_entry_get_text(GTK_ENTRY(serverIPEntry));
    char* serverPortStr = (char*)gtk_entry_get_text(GTK_ENTRY(sererPortEntry));

    int serverPort = atoi(serverPortStr);

    int status;

    gtk_widget_set_name(serverIPEntry, "fieldsNormal");
    gtk_label_set_text(GTK_LABEL(serverIPErrorLabel), "");

    // TODO: Check for valid IP and Port

    if (strcmp(serverIP, "") == 0) {

        gtk_widget_set_name(serverIPEntry, "fieldsError");
        gtk_label_set_text(GTK_LABEL(serverIPErrorLabel), "Please enter an IP");

        return -1;
    } else if (validate_ip(serverIP) == 1){
        // TODO: Check if IP Address given is valid
        g_print("Valid IP\n");
    } else {
        g_print("Invalid IP\n");
    }

    g_print("Selected Server IP: %s\n", selectedServerStr);
    gtk_widget_set_sensitive(connectButton, FALSE);
    append_to_log("Attempting connection, please wait...\n", 1);
    gtk_widget_set_sensitive(serverIPEntry, FALSE); // ERROR HAPPENING WHEN I RUN THIS LINE

    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(workingSetProgressBar), "Connecting...");
    status = pthread_create(&connThread, NULL, wait_for_connection, server_data);

    // TODO: Check thread status code
    if (status != 0) {
        printf("Thread returned error code %d\n", status);
        exit(-1);
    }

    return 1;
}

void *wait_for_connection(void* server_data) {

    struct data *srvDat = server_data;
    GtkWidget *disconnectButton = srvDat->disconnectButton;
    GtkWidget *connectButton = srvDat->connectButton;
    GtkWidget *statLabel = srvDat->statLabel;
    GtkWidget *serverIPEntry = srvDat->serverIPEntry;

    requestConnect = 1;

    for (int i = 0; i < 10; i++) {
        gtk_progress_bar_pulse(GTK_PROGRESS_BAR(workingSetProgressBar));
        g_print("Checking server...\n");

        // THIS BELOW IS FOR TESTING ONLY
        if (i == 4) {
            connected = 1;
        }
        // THIS ABOVE IS FOR TESTING ONLY

        if (connected == 1) {
            connSuccess = 1;
            break;
        }
        connSuccess = 0;
        sleep(1);
    }

    if (connSuccess == 1) {
        g_print("Connected to: %s\n", selectedServerStr);
        printf("Conn success\n");
        // TODO: Change button to disconnect button
        // TODO: Set progress to 0

        gtk_widget_hide(connectButton);
        gtk_widget_show(disconnectButton);

        gtk_widget_set_name(statLabel, "connLabel");
        gtk_label_set_text(GTK_LABEL(statLabel), "Connected");

        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(workingSetProgressBar), 0);
        gtk_progress_bar_set_text(GTK_PROGRESS_BAR(workingSetProgressBar), NULL);

        char* connLog = "Connected To: ";

        char* strToLog;

        if((strToLog = malloc(strlen(connLog)+strlen(selectedServerStr)+5)) != NULL){
            strToLog[0] = '\0';
            strcat(strToLog, connLog);
            strcat(strToLog, selectedServerStr);
            strcat(strToLog, "\n");
        } else {
            // TODO: Deal with failed malloc
        }

        append_to_log(strToLog, 1);
        pthread_exit(&connThread);

    } else if (connSuccess == 0) {
        gtk_widget_set_sensitive(serverIPEntry, TRUE);
        gtk_widget_set_sensitive(connectButton, TRUE);
        printf("Conn failed\n");
        append_to_log("Connection failed\n", 1);
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(workingSetProgressBar), 0);
        gtk_progress_bar_set_text(GTK_PROGRESS_BAR(workingSetProgressBar), "Disconnected");
        pthread_exit(&connThread);
    }
}

And here is the function validate_ip() that I am using to validate the entry as an IP Address, which seems to have led to this issue:

int validate_number(char *str) {
    while (*str) {
        if(!isdigit(*str)){ //if the character is not a number, return false
            return 0;
        }
        str++; //point to next character
    }
    return 1;
}

int validate_ip(char *ip) { //check whether the IP is valid or not
    int i, num, dots = 0;
    char *ptr;
    if (ip == NULL)
        return 0;
    ptr = strtok((char*)ip, "."); //cut the string using dot delimiter
    if (ptr == NULL)
        return 0;
    while (ptr) {
        if (!validate_number(ptr)) //check whether the sub string is holding only number or not
            return 0;
        num = atoi(ptr); //convert substring to number
        if (num >= 0 && num <= 255) {
            ptr = strtok(NULL, "."); //cut the next part of the string
            if (ptr != NULL)
                dots++; //increase the dot count
        } else
            return 0;
    }
    if (dots != 3) //if the number of dots are not 3, return false
        return 0;
    return 1;
}

Any help would be greatly appreciated. Thanks!

1

There are 1 best solutions below

0
On BEST ANSWER

Just managed to fix this issue by changing the start of the validate_ip() function to as follows:

int validate_ip(char *ipOrig) { //check whether the IP is valid or not
    char* ip[17];
    strcpy((char*)ip, ipOrig);
    int i, num, dots = 0;
    char *ptr;
....

Looks like it was an issue to do with the validate_ip() function changing the value of the variable passed into it, so I duplicated the incoming variable to be used within the function.