20-cleanup.dpatch 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #! /bin/sh -e
  2. ## 20-cleanup.dpatch by Theodore Ts'o <tytso@mit.edu>
  3. ##
  4. ## DP: Make sure the database store and the imap database is closed
  5. ## DP: if isync is aborted.
  6. [ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts
  7. patch_opts="${patch_opts:--f --no-backup-if-mismatch}"
  8. if [ $# -ne 1 ]; then
  9. echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
  10. exit 1
  11. fi
  12. case "$1" in
  13. -patch) patch $patch_opts -p1 < $0;;
  14. -unpatch) patch $patch_opts -p1 -R < $0;;
  15. *)
  16. echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
  17. exit 1;;
  18. esac
  19. exit 0
  20. @DPATCH@
  21. Problem description:
  22. >> If isync dies in the middle of synchronization, or the network
  23. >> connection breaks while it is synchronizing a mailbox, new messages
  24. >> which are downloaded from the IMAP server do not have their UID saved
  25. >> to the maildir directory. This is REALLY, REALLY BAD, because it
  26. >> means that on the next isync, the downloaded messages are re-uploaded
  27. >> to the imap server, resulting in duplicate messages in the IMAP store.
  28. >>
  29. >> This takes means the network download takes longer, and if the network
  30. >> connection is unrealible, it means it's more likely the the IMAP
  31. >> connection will break, resulting in more duplicate messages being
  32. >> uploaded to the servers. (The first time, 14 messages were uploaded
  33. >> to the server. The second time I re-isynced, 65 messages were
  34. >> uploaded to the server, resulting in some 79 duplicate messages that I
  35. >> had to manually weed out. Grr, grr, grr, grr.)
  36. Problem solution:
  37. Actually, I managed to figure out the solution a while ago, and got
  38. hung up trying to figure out the right way to submit the patches back
  39. to upstream (there's no mailing list that I can find; so do you just
  40. communicate directly with the developers). Anyway, I got busy and I
  41. never had a chance to send the patches a while ago.
  42. This patch is not the best, but it does seem to work. Perhaps a
  43. better approach would be to use the more advanced API's available with
  44. berkdb, so you can actually force a sync to the db/dbm files after
  45. the mail message has been downloaded. Fundamentally, that's the
  46. problem. The id has been added to the db file, but the changes don't
  47. get forced out to disk, so in the case of an abnormal termination of
  48. the program, the id's never get written to disk.
  49. The patch enclosed below solves the problem by establishing a signal
  50. handler, which cleans up in the case of the user typing ^C (after the
  51. network connection has gone away, say because your GSM phone's GPRS
  52. connection has gotten flakey, for example). However, it doesn't solve
  53. the problem in case of an abrupt system crash. In order to address
  54. that problem, the overall program interfaces would have to be changed
  55. to use the newer berkdb interfaces directly, but that would mean
  56. dropping compatibility with the ancient dbm interface. Personally, I
  57. don't think that to be any great loss, but the changes would be much
  58. more invasive, and would require agreement with the upstream
  59. maintainer that this is the right way to go.
  60. Also, for bonus points, perhaps there should be an inactivity timer so
  61. that isync can automatically figure out when the network connection
  62. has gone away, and can do a clean shutdown and exit automatically,
  63. instead of requiring the user to type ^C.
  64. - Ted
  65. Patched files: src/main.c
  66. ===================================================================
  67. RCS file: isync-0.9.2/src/RCS/main.c,v
  68. retrieving revision 1.3
  69. diff -u -r1.3 isync-0.9.2/src/main.c
  70. --- isync-0.9.2/src/main.c 2004/01/10 01:13:38 1.3
  71. +++ isync-0.9.2/src/main.c 2004/01/10 01:14:34
  72. @@ -35,6 +35,7 @@
  73. #include <string.h>
  74. #include <ctype.h>
  75. #include <dirent.h>
  76. +#include <signal.h>
  77. int Quiet;
  78. @@ -92,6 +93,22 @@
  79. unsigned int Tag = 0;
  80. char Hostname[256];
  81. int Verbose = 0;
  82. +mailbox_t *CleanupMail = 0;
  83. +imap_t *CleanupImap = 0;
  84. +int CleanupValid = 0;
  85. +
  86. +static void signal_exit(int sig)
  87. +{
  88. + info("Abort received\n");
  89. + if (CleanupValid) {
  90. + info("Aborting, cleaning up\n");
  91. + if (CleanupMail)
  92. + maildir_close (CleanupMail);
  93. + if (CleanupImap)
  94. + imap_close (CleanupImap);
  95. + }
  96. + exit (1);
  97. +}
  98. static void
  99. version (void)
  100. @@ -319,6 +336,10 @@
  101. usage (1);
  102. }
  103. + signal(SIGTERM, signal_exit);
  104. + signal(SIGHUP, signal_exit);
  105. + signal(SIGINT, signal_exit);
  106. +
  107. gethostname (Hostname, sizeof (Hostname));
  108. load_config (config, &o2o);
  109. @@ -410,6 +431,9 @@
  110. ret = 1;
  111. break;
  112. }
  113. + CleanupValid = 1;
  114. + CleanupMail = mail;
  115. + CleanupImap = imap;
  116. info ("Synchronizing\n");
  117. i = (delete || box->delete) ? SYNC_DELETE : 0;
  118. @@ -460,6 +484,8 @@
  119. } while (0);
  120. + CleanupValid = 0;
  121. +
  122. /* we never sync the same mailbox twice, so close it now */
  123. if (mail)
  124. maildir_close (mail);