tree_add由另一个线程中的g_idle_add调用 奇怪的行为是散列是垃圾,消息摘要怎么会乱码?
其余的奇怪行为已通过以下建议修复
#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;
}
制作
gcc -c main.c -o test `pkg-config --cflags --libs gtk+-3.0` -lcrypto -lgcrypt -lpthread