tree_add is called by g_idle_add in another thread
odd behaviour is that the hash is garbage, how would the message digest end up garbled?
the rest of the odd behaviour has been fixed with the below suggestions
#include <pthread.h>
#include <openssl/evp.h>
#include <gcrypt.h>
#include <gtk/gtk.h>
unsigned char *mdSHA256(char *data, size_t *len) {
unsigned char *md = calloc(33, sizeof(char));
int mdlen;
EVP_MD_CTX *mdctx;
EVP_add_digest(EVP_sha256());
mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
EVP_DigestUpdate(mdctx, data, *len);
EVP_DigestFinal_ex(mdctx, md, &mdlen);
EVP_MD_CTX_destroy(mdctx);
EVP_cleanup();
*len = mdlen;
return md;
}
struct peer {
int approved;
int port;
unsigned char *address;
gcry_sexp_t pubkey;
struct sf_connection *connection;
struct peer *next;
struct peer *prev;
};
struct peer *peers = NULL;
struct peer *peer_new() {
struct peer *_peer = malloc(sizeof(struct peer));
if(peers == NULL) {
_peer->next = _peer;
_peer->prev = _peer;
peers = _peer;
}
else {
peers->prev->next = _peer;
_peer->prev = peers->prev;
peers->prev = _peer;
_peer->next = peers;
}
return _peer;
}
void *mainthread(void *m) { //code removed so you can run this
sleep(2);
struct peer *new_peer = new_peer();
new_peer->port = 66666;
new_peer->address = "127.0.0.1";
new_peer->pubkey = NULL;
new_peer->approved = 0;
g_idle_add(tree_add, new_peer);
}
gboolean tree_add(gpointer data) {
struct peer *new_peer = data;
GtkTreeIter iter;
size_t size = gcry_sexp_sprint(new_peer->pubkey, GCRY SEXP_FMT_ADVANCED, NULL, 0);
char *buf = malloc(size);
gcry_sexp_sprint(new_peer->pubkey, GCRYSEXP_FMT_ADVANCED, buf, size);
unsigned char *md = mdSHA256(buf, &size);
gtk_tree_store_append(serverstore, &iter, NULL);
gtk_tree_store_set(serverstore, &iter,
COL_IP, new_peer->address,
COL_PORT, new_peer->port,
COL_PUBKEYMD, md,
COL_APPROVED, new_peer->approved,
-1);
free(buf);
free(md);
return 0;
}
GtkWidget *setup_tree() {
GtkWidget *tree;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
serverstore = gtk_tree_store_new(N_COLUMNS,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(serverstore));
g_object_unref(G_OBJECT(serverstore));
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("IP", renderer, "text", COL_IP, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Port", renderer, "text", COL_PORT, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("PubKey", renderer, "text", COL_PUBKEYMD, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
renderer = gtk_cell_renderer_toggle_new();
column = gtk_tree_view_column_new_with_attributes("Approved", renderer, "active", COL_APPROVED, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
return tree;
}
void on_window_main_destroy() {
raise(SIGINT);
gtk_main_quit();
}
int main(int argc, char **argv) {
GtkWidget *window;
GtkWidget *view;
pthread_t main_thread;
if(pthread_create(&main_thread, NULL, mainthread, NULL)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "destroy", on_window_main_destroy, NULL);
gtk_window_set_title(GTK_WINDOW(window), "ProjXverse Master");
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
view = setup_tree();
gtk_container_add(GTK_CONTAINER(window), view);
gtk_widget_show_all(window);
gtk_main();
pthread_join(main_thread, NULL);
return 0;
}
to make
gcc -c main.c -o test `pkg-config --cflags --libs gtk+-3.0` -lcrypto -lgcrypt -lpthread