Releases: gavindi/MtSync
Releases · gavindi/MtSync
Release list
0.9.13 - Public Release
First public announcement release.
0.9.13 - Tray "Open" Fix
- Tray "Open" required two clicks when "Start minimized" was enabled: the GUI process spawned by the tray honoured the
start_minimizedsetting and started hidden, so the first click launched an invisible window and only the second click (routed via IPCshow_windowto the now-connected client) presented it — the daemon now spawns the GUI with a new--showflag that overridesstart_minimizedon first activation, so an explicit tray click always shows the window immediately;start_minimizedstill applies to plainmtsynclaunches such as login autostart - Daemon/GUI mutual spawning prefers
/proc/self/exeover PATH lookup: both the daemon launching a GUI and the GUI launching a daemon previously resolvedmtsyncviaGlib::find_program_in_pathfirst, so a development build would silently launch a stale system-installed binary; the running executable's own path is now preferred, with PATH lookup as fallback
0.9.12
Changelog
0.9.12 - Change of tagline
- Changed tagline: Changed the tagline from "Mount or sync network storage in comfort" to "Mount or sync network storage anywhere"
0.9.11 — Race Condition & Safety Fixes
- Null deref on daemon shutdown with in-flight jobs:
done_cbnow returns immediately whenm_runningis false — previously, stopping the daemon while a sync/copy/move submission was in-flight caused libsoup to fire the completion callback afterm_trayandm_ipc_serverhad already been reset to nullptr, crashing the daemon - Use-after-free in CompareDialog on WM close: an
m_aliveshared-ptr sentinel is set to false in asignal_close_requesthandler; action-button async callbacks (delete_files,copy_files) capture aweak_ptrand bail out if the dialog was destroyed before the operation completed — previously only the cancel button set the cancellation flag, leaving WM-close unguarded - Use-after-free in BackendsView idle callbacks:
populate()now creates a newm_populate_tokenon each call, invalidating allweak_ptrcopies held by in-flightget_aboutcallbacks and their posted idle closures — previously a theme change or secondrefresh()call could destroy widget rows while a prior round's idle callbacks still held rawGtk::Label*/Gtk::ProgressBar*pointers - Timer leak in
schedule_joband retry path:sched_timer.disconnect()is now called before overwriting the connection inschedule_job();retry_timer.disconnect()likewise before the retry assignment inon_job_completed()— previously the old GLib timeout source survived until its next fire, potentially triggering an unintended duplicate job start - Integer overflow (UB) in retry backoff: the left-shift
2000u << (retry_count - 1)is now clamped to a maximum shift of 4 before the shift executes — previously a user-configured retry count ≥ 33 caused a shift of ≥ 32 on an unsigned 32-bit value, which is undefined behaviour in C++ notify-send/kdialogblocking the GLib main loop: bothGlib::spawn_synccalls innotification.cppreplaced withGlib::spawn_async— the previous blocking spawn suspended all IPC message processing, timer callbacks, and HTTP response callbacks for the duration of the notification helper process- Unchecked
fcntlreturn values:F_GETFLreturn value is now tested beforeF_SETFLinipc/client.cppand both call-sites inipc/server.cpp— a failure returned -1 which, OR-ed withO_NONBLOCK, set arbitrary flags on the file descriptor and could leave the socket in blocking mode g_signal_connectwith no disconnect in SettingsView: added~SettingsView()destructor that callsg_signal_handler_disconnecton all 12 stored handler IDs; IDs are now captured from theg_signal_connectreturn values at setup time, matching the pattern already used inBackendsView
0.9.10 — Animated About Logo
- Animated logo on About tab: the static application icon is replaced with the 16-frame Mt. Sync smoke animation — frames are loaded from a 4096×256 horizontal spritesheet embedded in GLib resources and rendered via a
Gtk::DrawingAreausing Cairo; the animation runs at 80 ms per frame (matching the original APNG timing) and starts/stops automatically when the About tab is shown or hidden
0.9.9
Many changes ahead of the 1.0.0 release. Mostly around usability by giving UI elements tooltips to explain their actions.
Recent changes since last release:
0.9.9 — Toggle Tooltips
- Verbose tooltips on all toggle switches: all 12
AdwSwitchRowtoggles in the Settings tab and Job Edit dialog now have descriptive tooltips — Settings toggles (On Job Start, On Completion, On Completion with Errors/Warnings, Start daemon on login, Start minimized to tray, Shutdown daemon when closing, Verify checksums) and Job Edit toggles (Dry Run, Bi-directional sync, Enable Checksum, Mount at Start-up, Enable Schedule) each explain what the toggle does and any relevant consequences of changing it
0.9.8 — Button Tooltips
- Verbose tooltips on all buttons: every interactive button in the GUI now has a descriptive tooltip — 23 buttons that previously had none (job run/stop/edit/delete/expand, add job, add remote, edit/delete remote, authorize OAuth, save/cancel in all dialogs, cron field clear, compare pagination, log file open) have been annotated, and 20 existing short tooltips (Back, Up, Refresh, Copy, Move, Sync, Mount, Swap, Delete, Compare, New Folder, and all Compare dialog filter/action buttons) have been rewritten as full sentences describing what the button does and any destructive consequences
0.9.7 — Performance Improvements Sprint 3
- Release builds use
-O3 -flto:CMakeLists.txtnow enables-O3and link-time optimisation forReleasebuilds viatarget_compile_options/target_link_optionsguards — previously Release builds relied on CMake's default-O2with no LTO - Shutdown
waitpidpoll granularity reduced from 50 ms to 5 ms: the SIGTERM → SIGKILL escalation loop instop_daemon()previously slept 50 ms between eachwaitpid(WNOHANG)check, adding up to 50 ms of unnecessary latency after the process has already exited; the interval is now 5 ms so a cooperative rclone exit is detected within one tick rather than up to ten - Mount-point membership check:
std::set→std::unordered_set: thelive_mountsset constructed on each 60-second mount health-check tick now usesstd::unordered_set<std::string>—.count()lookups drop from O(log n) to O(1) average;#include <set>replaced with<unordered_set>
0.9.6 — Performance Improvements Sprint 2
- HTTP session timeout reduced from 15 s to 5 s: all rclone RC requests now time out after 5 seconds — the previous 15-second limit meant a hung localhost rclone could stall 10 concurrent poll callbacks for 15 s each before the async queue drained; 5 s is sufficient for a local loopback call
- Mount health timer skips HTTP call when no mounts are active: the 60-second
list_mountsliveness check now returns early if no jobs of type Mount are currently active, avoiding a pointless HTTP round-trip every minute during normal sync-only use - Cron
day_of_weekcomputed once per day: the next-occurrence search previously calledday_of_week()on every iteration of the up-to-2.1 M step minute loop — the result is now cached and recomputed only when the date changes, reducing calls by up to 1440× per day - Compare dialog pagination: O(3n) → O(n) per filter change:
show_page,update_pagination_controls, andapply_filterseach scannedm_all_rowsindependently; the filter+strip pass is now computed once inrebuild_filter_cache()into am_filtered_rowscache that all three callers read, eliminating two redundant full-list traversals per filter toggle or page navigation - Compare dialog status column: CSS class swap guarded: the status-column bind callback previously removed all five CSS classes unconditionally on every scroll event; it now stores the current class via
g_object_set_dataand only removes the old class and adds the new one when they differ - Browser pane name column: dynamic casts replaced and CSS swap guarded: the name-column bind callback previously traversed the widget tree with two
dynamic_castcalls and removed 12 CSS classes unconditionally on every scroll event; widget pointers are now stored in the setup callback viag_object_set_dataand retrieved in O(1) in the bind callback, and the icon CSS class is only swapped when it changes
0.9.5 — Performance Improvements Sprint 1
- Parallel job-state vectors consolidated into a struct: eight separate
std::vectors (m_poll_timers,m_sched_timers,m_retry_timers,m_job_ids,m_job_submitting,m_poll_in_flight,m_retry_counts,m_last_stats) replaced by a singlestd::vector<JobState>— job deletion now performs oneO(n)erase instead of eight, all per-job state is cache-locally contiguous, and independent resize calls scattered across the daemon are eliminated - Redundant
get_statsHTTP call on job completion removed:on_job_completedpreviously fired a secondcore/statsHTTP round-trip to fetch final transfer counts despite the poll loop already caching them inm_last_stats(nowJobState::last_stats) at most 500 ms earlier; completion now uses the cached value directly, eliminating one RC call per job lifecycle job_updatedno longer rebuilds the entire job list: thejob_updateddaemon broadcast previously calledrebuild_ui()which disconnected all timers, removed every row widget, and recreated the full list; it now removes and recreates only the single affected row —O(1)widget operations instead ofO(n)- Activity log not re-read on job start:
refresh_log()was called onjob_startedin addition tojob_completedandjob_stopped; the log file does not change meaningfully mid-transfer so the disk read on start is removed — log view refreshes only on terminal job events
Full Changelog: 0.9.8...0.9.9
0.9.4
Full Changelog: 0.9.3...0.9.4
First public release of Mt Sync (pronounced Mount Sync).