aboutsummaryrefslogtreecommitdiff
path: root/internal/imap
diff options
context:
space:
mode:
authorRené 'Necoro' Neumann <necoro@necoro.eu>2020-04-23 23:47:05 +0200
committerRené 'Necoro' Neumann <necoro@necoro.eu>2020-04-23 23:47:05 +0200
commit6911562cf4214531343b7509afe77e38b28a0801 (patch)
tree46601b14d15b781c373a99f32880334b10092c68 /internal/imap
parentc1fbae6e0f5981d4d60f5b614d5d195ae5cde4a8 (diff)
downloadfeed2imap-go-6911562cf4214531343b7509afe77e38b28a0801.tar.gz
feed2imap-go-6911562cf4214531343b7509afe77e38b28a0801.tar.bz2
feed2imap-go-6911562cf4214531343b7509afe77e38b28a0801.zip
Fix concurrent access to the same folder
Diffstat (limited to '')
-rw-r--r--internal/imap/connection.go7
-rw-r--r--internal/imap/mailboxes.go41
2 files changed, 43 insertions, 5 deletions
diff --git a/internal/imap/connection.go b/internal/imap/connection.go
index 88b1496..358445b 100644
--- a/internal/imap/connection.go
+++ b/internal/imap/connection.go
@@ -99,6 +99,13 @@ func (conn *connection) ensureFolder(folder Folder) error {
return nil
}
+ if conn.mailboxes.locking(folder) {
+ // someone else tried to create the MB -- try again, now that he's done
+ return conn.ensureFolder(folder)
+ } else {
+ defer conn.mailboxes.unlocking(folder)
+ }
+
log.Printf("Checking for folder '%s'", folder)
mbox, found, err := conn.list(folder.str)
diff --git a/internal/imap/mailboxes.go b/internal/imap/mailboxes.go
index d0fdede..f1dc6c6 100644
--- a/internal/imap/mailboxes.go
+++ b/internal/imap/mailboxes.go
@@ -7,8 +7,38 @@ import (
)
type mailboxes struct {
- mb map[string]*imap.MailboxInfo
- mu sync.RWMutex
+ mb map[string]*imap.MailboxInfo
+ mu sync.RWMutex
+ changeLocks map[string]chan struct{}
+}
+
+func (mbs *mailboxes) unlocking(elem Folder) {
+ mbs.mu.Lock()
+ defer mbs.mu.Unlock()
+
+ ch, ok := mbs.changeLocks[elem.str]
+ if !ok {
+ panic("Unlocking where nothing is locked")
+ }
+ close(ch)
+ delete(mbs.changeLocks, elem.str)
+}
+
+func (mbs *mailboxes) locking(elem Folder) bool {
+ mbs.mu.Lock()
+ ch, ok := mbs.changeLocks[elem.str]
+ if !ok {
+ ch = make(chan struct{})
+ mbs.changeLocks[elem.str] = ch
+ mbs.mu.Unlock()
+ // we created the lock, we are in charge and done here
+ return false
+ } else {
+ // someone else is working, we wait till he's done
+ mbs.mu.Unlock() // we are not doing anything...
+ <-ch
+ return true
+ }
}
func (mbs *mailboxes) contains(elem Folder) bool {
@@ -28,7 +58,8 @@ func (mbs *mailboxes) add(elem *imap.MailboxInfo) {
func NewMailboxes() *mailboxes {
return &mailboxes{
- mb: map[string]*imap.MailboxInfo{},
- mu: sync.RWMutex{},
+ mb: map[string]*imap.MailboxInfo{},
+ changeLocks: map[string]chan struct{}{},
+ mu: sync.RWMutex{},
}
-} \ No newline at end of file
+}
-p.Jason A. Donenfeld1-9/+3 2014-04-18Abstract remove empty directories into function.Jason A. Donenfeld1-14/+11 2014-04-18Remember to prune empty folders.Jason A. Donenfeld1-0/+8 2014-04-18init: allow deinitializationJason A. Donenfeld2-2/+18 2014-04-18bash-completion: filter dot files from resultsJason A. Donenfeld1-3/+8 2014-04-18reencrypt: remove option, do automaticallyJason A. Donenfeld5-39/+25 2014-04-18reencryption: add to completion filesJason A. Donenfeld3-1/+5 2014-04-18Specify variable gpg.Jason A. Donenfeld1-1/+1 2014-04-18style: don't escape new line on &&Jason A. Donenfeld1-2/+2 2014-04-18reencryption: remove temporary file on failureJason A. Donenfeld1-1/+1 2014-04-18reencryption: only reencrypt files when requiredJason A. Donenfeld2-16/+37 2014-04-17cp: typo as cvJason A. Donenfeld1-1/+1 2014-04-17bash: gpg_id is localJason A. Donenfeld1-0/+1 2014-04-17move/copy: always reencrypt passwords at destinationJason A. Donenfeld5-25/+56 2014-04-17makefile: allow platform files with gnu sedJason A. Donenfeld1-7/+8 Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> 2014-04-17mv: Add pass mv/rename supportJason A. Donenfeld5-3/+78 Based-on-work-by: Matthieu Weber <mweber@free.fr> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> 2014-04-17revelation2pass: add plain XML importJavali1-11/+15 I found that revelatio2pass.py script doesn't work. It can not decrypt my password file. I got following error message: raceback (most recent call last): File "git/password-store/contrib/importers/revelation2pass.py", line 159, in <module> main(args.FILE, verbose=args.verbose, xml=args.xml) File "git/password-store/contrib/importers/revelation2pass.py", line 140, in main cleardata_gz = decrypt_gz(password, data) File "git/password-store/contrib/importers/revelation2pass.py", line 117, in decrypt_gz ct = c.decrypt(cipher_text[28:]) File "/usr/lib/python2.7/site-packages/Crypto/Cipher/blockalgo.py", line 295, in decrypt return self._cipher.decrypt(ciphertext) I was unable to fix the problem, but I created a workaround, that add plain XML import option to the revelation2pass.py script. Revelation can export its password file as plain XML format. 2014-04-17platform: add cygwin supportJason A. Donenfeld2-1/+17 According to Brandon Jones, all we need to do is adjust /dev/clipboard from xclip. So we add a platform specific file to do so. http://www.relaytheurgency.com/2014/04/pass-in-cygwin-relatively-simple.html Suggested-by: Brandon Jones <jones.brandon.lee@gmail.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>