Fix multiple mem leaks, refactor and improve memory management #10
53
prof.supp
53
prof.supp
@@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
# This file is a combination of our own rules and
|
# This file is a combination of our own rules and
|
||||||
# * the glib2 suppressions file that usually can be found at /usr/share/glib-2.0/valgrind/glib.supp
|
# * the glib2 suppressions file that usually can be found at /usr/share/glib-2.0/valgrind/glib.supp
|
||||||
# * python suppressions file from http://svn.python.org/projects/python/trunk/Misc/valgrind-python.supp
|
# * python suppressions file from https://github.com/python/cpython/blob/main/Misc/valgrind-python.supp
|
||||||
#
|
#
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1557,6 +1557,10 @@
|
|||||||
...
|
...
|
||||||
fun:xdg_mime_init
|
fun:xdg_mime_init
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Python Valgrind .supp start
|
||||||
|
# taken from https://github.com/python/cpython/blob/main/Misc/valgrind-python.supp
|
||||||
|
|
||||||
#
|
#
|
||||||
# This is a valgrind suppression file that should be used when using valgrind.
|
# This is a valgrind suppression file that should be used when using valgrind.
|
||||||
#
|
#
|
||||||
@@ -1654,6 +1658,49 @@
|
|||||||
fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
|
fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Leaks: dlopen() called without dlclose()
|
||||||
|
#
|
||||||
|
|
||||||
|
{
|
||||||
|
dlopen() called without dlclose()
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:malloc
|
||||||
|
fun:strdup
|
||||||
|
fun:_dl_load_cache_lookup
|
||||||
|
}
|
||||||
|
{
|
||||||
|
dlopen() called without dlclose()
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:malloc
|
||||||
|
fun:strdup
|
||||||
|
fun:_dl_map_object
|
||||||
|
}
|
||||||
|
{
|
||||||
|
dlopen() called without dlclose()
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:*
|
||||||
|
fun:_dl_new_object
|
||||||
|
}
|
||||||
|
{
|
||||||
|
dlopen() called without dlclose()
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:*
|
||||||
|
fun:_dl_new_object
|
||||||
|
}
|
||||||
|
{
|
||||||
|
dlopen() called without dlclose()
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:calloc
|
||||||
|
fun:*
|
||||||
|
fun:_dl_check_map_versions
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Non-python specific leaks
|
# Non-python specific leaks
|
||||||
#
|
#
|
||||||
@@ -2048,6 +2095,10 @@
|
|||||||
fun:PyUnicode_FSConverter
|
fun:PyUnicode_FSConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Python Valgrind .supp end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Actual GTK things
|
# Actual GTK things
|
||||||
{
|
{
|
||||||
GtkWidgetClass action GPtrArray
|
GtkWidgetClass action GPtrArray
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_las
|
|||||||
// null the current time is used. from_start gets first few messages if true
|
// null the current time is used. from_start gets first few messages if true
|
||||||
// otherwise the last ones. Flip flips the order of the results
|
// otherwise the last ones. Flip flips the order of the results
|
||||||
db_history_result_t
|
db_history_result_t
|
||||||
log_database_get_previous_chat(const gchar* const contact_barejid, const char* start_time, char* end_time, gboolean from_start, gboolean flip, GSList** result)
|
log_database_get_previous_chat(const gchar* const contact_barejid, const gchar* start_time, const gchar* end_time, gboolean from_start, gboolean flip, GSList** result)
|
||||||
{
|
{
|
||||||
if (!g_chatlog_database) {
|
if (!g_chatlog_database) {
|
||||||
log_warning("log_database_get_previous_chat() called but db is not initialized");
|
log_warning("log_database_get_previous_chat() called but db is not initialized");
|
||||||
@@ -337,7 +337,7 @@ log_database_get_previous_chat(const gchar* const contact_barejid, const char* s
|
|||||||
gchar* sort1 = from_start ? "ASC" : "DESC";
|
gchar* sort1 = from_start ? "ASC" : "DESC";
|
||||||
gchar* sort2 = !flip ? "ASC" : "DESC";
|
gchar* sort2 = !flip ? "ASC" : "DESC";
|
||||||
GDateTime* now = g_date_time_new_now_local();
|
GDateTime* now = g_date_time_new_now_local();
|
||||||
auto_gchar gchar* end_date_fmt = end_time ? end_time : g_date_time_format_iso8601(now);
|
auto_gchar gchar* end_date_fmt = end_time ? g_strdup(end_time) : g_date_time_format_iso8601(now);
|
||||||
auto_sqlite gchar* query = sqlite3_mprintf("SELECT * FROM ("
|
auto_sqlite gchar* query = sqlite3_mprintf("SELECT * FROM ("
|
||||||
"SELECT COALESCE(B.`message`, A.`message`) AS message, "
|
"SELECT COALESCE(B.`message`, A.`message`) AS message, "
|
||||||
"A.`timestamp`, A.`from_jid`, A.`from_resource`, A.`to_jid`, A.`to_resource`, A.`type`, A.`encryption`, A.`stanza_id` FROM `ChatLogs` AS A "
|
"A.`timestamp`, A.`from_jid`, A.`from_resource`, A.`to_jid`, A.`to_resource`, A.`type`, A.`encryption`, A.`stanza_id` FROM `ChatLogs` AS A "
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ void log_database_add_incoming(ProfMessage* message);
|
|||||||
void log_database_add_outgoing_chat(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
void log_database_add_outgoing_chat(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
||||||
void log_database_add_outgoing_muc(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
void log_database_add_outgoing_muc(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
||||||
void log_database_add_outgoing_muc_pm(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
void log_database_add_outgoing_muc_pm(const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc);
|
||||||
db_history_result_t log_database_get_previous_chat(const gchar* const contact_barejid, const char* start_time, char* end_time, gboolean from_start, gboolean flip, GSList** result);
|
db_history_result_t log_database_get_previous_chat(const gchar* const contact_barejid, const gchar* start_time, const gchar* end_time, gboolean from_start, gboolean flip, GSList** result);
|
||||||
ProfMessage* log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_last);
|
ProfMessage* log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_last);
|
||||||
void log_database_close(void);
|
void log_database_close(void);
|
||||||
|
|
||||||
|
|||||||
@@ -900,6 +900,8 @@ _python_type_error(ProfPlugin* plugin, char* hook, char* type)
|
|||||||
g_string_free(err_msg, TRUE);
|
g_string_free(err_msg, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts a Python string or None result to a C string and decreases the Python object's reference count.
|
||||||
|
// If the result is NULL, or not a string/unicode/bytes/None, logs an error and returns NULL.
|
||||||
static char*
|
static char*
|
||||||
_handle_string_or_none_result(ProfPlugin* plugin, PyObject* result, char* hook)
|
_handle_string_or_none_result(ProfPlugin* plugin, PyObject* result, char* hook)
|
||||||
{
|
{
|
||||||
@@ -910,18 +912,16 @@ _handle_string_or_none_result(ProfPlugin* plugin, PyObject* result, char* hook)
|
|||||||
}
|
}
|
||||||
#ifdef PY_IS_PYTHON3
|
#ifdef PY_IS_PYTHON3
|
||||||
if (result != Py_None && !PyUnicode_Check(result) && !PyBytes_Check(result)) {
|
if (result != Py_None && !PyUnicode_Check(result) && !PyBytes_Check(result)) {
|
||||||
allow_python_threads();
|
|
||||||
_python_type_error(plugin, hook, "string, unicode or None");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (result != Py_None && !PyUnicode_Check(result) && !PyString_Check(result)) {
|
if (result != Py_None && !PyUnicode_Check(result) && !PyString_Check(result)) {
|
||||||
|
#endif
|
||||||
|
Py_XDECREF(result);
|
||||||
allow_python_threads();
|
allow_python_threads();
|
||||||
_python_type_error(plugin, hook, "string, unicode or None");
|
_python_type_error(plugin, hook, "string, unicode or None");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
char* result_str = python_str_or_unicode_to_string(result);
|
char* result_str = python_str_or_unicode_to_string(result);
|
||||||
|
Py_XDECREF(result);
|
||||||
allow_python_threads();
|
allow_python_threads();
|
||||||
return result_str;
|
return result_str;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "glib.h"
|
||||||
#include "xmpp/chat_session.h"
|
#include "xmpp/chat_session.h"
|
||||||
#include "window_list.h"
|
#include "window_list.h"
|
||||||
#include "xmpp/roster_list.h"
|
#include "xmpp/roster_list.h"
|
||||||
@@ -585,10 +586,12 @@ _chatwin_history(ProfChatWin* chatwin, const char* const contact_barejid)
|
|||||||
// first entry's timestamp in the buffer is used. Flip true to prepend to buffer.
|
// first entry's timestamp in the buffer is used. Flip true to prepend to buffer.
|
||||||
// Timestamps should be in iso8601
|
// Timestamps should be in iso8601
|
||||||
db_history_result_t
|
db_history_result_t
|
||||||
chatwin_db_history(ProfChatWin* chatwin, const char* start_time, char* end_time, gboolean flip)
|
chatwin_db_history(ProfChatWin* chatwin, const gchar* start_time, const gchar* end_time, gboolean flip)
|
||||||
{
|
{
|
||||||
if (!end_time) {
|
auto_gchar gchar* _end_time = NULL;
|
||||||
end_time = buffer_size(((ProfWin*)chatwin)->layout->buffer) == 0 ? NULL : g_date_time_format_iso8601(buffer_get_entry(((ProfWin*)chatwin)->layout->buffer, 0)->time);
|
if (!end_time && buffer_size(((ProfWin*)chatwin)->layout->buffer) > 0) {
|
||||||
|
jabber.developer marked this conversation as resolved
Outdated
|
|||||||
|
_end_time = g_date_time_format_iso8601(buffer_get_entry(((ProfWin*)chatwin)->layout->buffer, 0)->time);
|
||||||
|
end_time = _end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList* history = NULL;
|
GSList* history = NULL;
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ void chatwin_set_incoming_char(ProfChatWin* chatwin, const char* const ch);
|
|||||||
void chatwin_unset_incoming_char(ProfChatWin* chatwin);
|
void chatwin_unset_incoming_char(ProfChatWin* chatwin);
|
||||||
void chatwin_set_outgoing_char(ProfChatWin* chatwin, const char* const ch);
|
void chatwin_set_outgoing_char(ProfChatWin* chatwin, const char* const ch);
|
||||||
void chatwin_unset_outgoing_char(ProfChatWin* chatwin);
|
void chatwin_unset_outgoing_char(ProfChatWin* chatwin);
|
||||||
db_history_result_t chatwin_db_history(ProfChatWin* chatwin, const char* start_time, char* end_time, gboolean flip);
|
db_history_result_t chatwin_db_history(ProfChatWin* chatwin, const gchar* start_time, const gchar* end_time, gboolean flip);
|
||||||
|
|
||||||
// MUC window
|
// MUC window
|
||||||
ProfMucWin* mucwin_new(const char* const barejid);
|
ProfMucWin* mucwin_new(const char* const barejid);
|
||||||
|
|||||||
@@ -710,20 +710,22 @@ win_page_down(ProfWin* window, int scroll_size)
|
|||||||
// Scrolled down after reaching the bottom of the page
|
// Scrolled down after reaching the bottom of the page
|
||||||
if ((*page_start > total_rows - page_space || (*page_start == page_space && *page_start >= total_rows)) && window->type == WIN_CHAT) {
|
if ((*page_start > total_rows - page_space || (*page_start == page_space && *page_start >= total_rows)) && window->type == WIN_CHAT) {
|
||||||
int bf_size = buffer_size(window->layout->buffer);
|
int bf_size = buffer_size(window->layout->buffer);
|
||||||
if (bf_size > 0) {
|
if (bf_size > 0 && *scroll_state != WIN_SCROLL_REACHED_BOTTOM) {
|
||||||
|
// How many lines are left until end of the screen
|
||||||
|
int current_offset = total_rows - *page_start;
|
||||||
|
GDateTime* now = g_date_time_new_now_local();
|
||||||
ProfBuffEntry* last_entry = buffer_get_entry(window->layout->buffer, bf_size - 1);
|
ProfBuffEntry* last_entry = buffer_get_entry(window->layout->buffer, bf_size - 1);
|
||||||
|
jabber.developer marked this conversation as resolved
Outdated
jabber.developer
commented
Always free Always free `end_date` now, since `chatwin_db_history` stopped managing memory.
|
|||||||
auto_gchar gchar* start = g_date_time_format_iso8601(last_entry->time);
|
auto_gchar gchar* start = g_date_time_format_iso8601(last_entry->time);
|
||||||
GDateTime* now = g_date_time_new_now_local();
|
auto_gchar gchar* end_date = g_date_time_format_iso8601(now);
|
||||||
gchar* end_date = g_date_time_format_iso8601(now);
|
db_history_result_t db_response = chatwin_db_history((ProfChatWin*)window, start, end_date, FALSE);
|
||||||
g_date_time_unref(now);
|
if (db_response == DB_RESPONSE_EMPTY)
|
||||||
if (*scroll_state != WIN_SCROLL_REACHED_BOTTOM && !chatwin_db_history((ProfChatWin*)window, start, end_date, FALSE)) {
|
|
||||||
*scroll_state = WIN_SCROLL_REACHED_BOTTOM;
|
*scroll_state = WIN_SCROLL_REACHED_BOTTOM;
|
||||||
} else if (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) {
|
|
||||||
g_free(end_date);
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = last_entry->y_end_pos - 1;
|
// similar to page_up (see explanation there)
|
||||||
*page_start = offset - page_space + scroll_size;
|
// Get offset of the message that was the latest prior to loading messages from the DB
|
||||||
|
int original_pos = last_entry->y_end_pos;
|
||||||
|
*page_start = original_pos - current_offset;
|
||||||
|
g_date_time_unref(now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2752,6 +2752,22 @@ iq_mam_request(ProfChatWin* win, GDateTime* enddate)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trim the last 3 characters from the datetime string to remove unwanted suffix (timezone offset)
|
||||||
|
static void
|
||||||
|
_truncate_datetime_suffix(gchar* str)
|
||||||
|
jabber.developer marked this conversation as resolved
jabber.developer
commented
Safe datetime truncation in case of malformed datetime Safe datetime truncation in case of malformed datetime
|
|||||||
|
{
|
||||||
|
if (!str) {
|
||||||
|
log_warning("_truncate_datetime_suffix(): unexpected null datetime string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t len = strlen(str);
|
||||||
|
if (len >= 3) {
|
||||||
|
str[len - 3] = '\0';
|
||||||
|
} else {
|
||||||
|
log_warning("_truncate_datetime_suffix(): unexpected short datetime string: %s", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
|
_mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
|
||||||
{
|
{
|
||||||
@@ -2773,17 +2789,17 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
|
|||||||
|
|
||||||
buffer_remove_entry(window->layout->buffer, 0);
|
buffer_remove_entry(window->layout->buffer, 0);
|
||||||
|
|
||||||
auto_char char* start_str = NULL;
|
auto_gchar gchar* start_str = NULL;
|
||||||
if (data->start_datestr) {
|
if (data->start_datestr) {
|
||||||
start_str = strdup(data->start_datestr);
|
start_str = g_strdup(data->start_datestr);
|
||||||
// Convert to iso8601
|
// Convert to iso8601
|
||||||
start_str[strlen(start_str) - 3] = '\0';
|
_truncate_datetime_suffix(start_str);
|
||||||
}
|
}
|
||||||
char* end_str = NULL;
|
auto_gchar gchar* end_str = NULL;
|
||||||
if (data->end_datestr) {
|
if (data->end_datestr) {
|
||||||
end_str = strdup(data->end_datestr);
|
end_str = g_strdup(data->end_datestr);
|
||||||
// Convert to iso8601
|
// Convert to iso8601
|
||||||
end_str[strlen(end_str) - 3] = '\0';
|
_truncate_datetime_suffix(end_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_complete || !data->fetch_next) {
|
if (is_complete || !data->fetch_next) {
|
||||||
|
|||||||
@@ -644,7 +644,7 @@ _available_handler(xmpp_stanza_t* const stanza)
|
|||||||
const char* account_name = session_get_account_name();
|
const char* account_name = session_get_account_name();
|
||||||
int max_sessions = accounts_get_max_sessions(account_name);
|
int max_sessions = accounts_get_max_sessions(account_name);
|
||||||
if (max_sessions > 0) {
|
if (max_sessions > 0) {
|
||||||
const gchar* cur_resource = accounts_get_resource(account_name);
|
auto_gchar gchar* cur_resource = accounts_get_resource(account_name);
|
||||||
|
jabber.developer marked this conversation as resolved
jabber.developer
commented
Old mem leak fixed. Old mem leak fixed.
|
|||||||
int res_count = connection_count_available_resources();
|
int res_count = connection_count_available_resources();
|
||||||
if (res_count > max_sessions && g_strcmp0(cur_resource, resource->name)) {
|
if (res_count > max_sessions && g_strcmp0(cur_resource, resource->name)) {
|
||||||
ProfWin* console = wins_get_console();
|
ProfWin* console = wins_get_console();
|
||||||
|
|||||||
Reference in New Issue
Block a user
Mem leak fixed. Since
end_timebecame const, it's not freed within the method.auto_gchar gchar* _end_time is used as a temporary variable with autocleanup in case if
end_timeis not defined.