Skip to content
Snippets Groups Projects
Commit 36522b3b authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Fix UID FETCH deadlock.

Also, after grabbing a lock, enter a try/catch that will unlock
and re-throw the error.
parent ce677196
No related branches found
No related tags found
No related merge requests found
...@@ -1394,17 +1394,23 @@ function open_cfg(usr) ...@@ -1394,17 +1394,23 @@ function open_cfg(usr)
return false; return false;
} }
lock_cfg(); lock_cfg();
// Check if it's the old INI format... try {
if (cfgfile.length > 0) { // Check if it's the old INI format...
var ch = cfgfile.read(1); if (cfgfile.length > 0) {
if (ch != '{') { var ch = cfgfile.read(1);
// INI file, convert... if (ch != '{') {
read_old_cfg(); // INI file, convert...
read_old_cfg();
save_cfg(false);
}
}
else {
save_cfg(false); save_cfg(false);
} }
} }
else { catch (error) {
save_cfg(false); unlock_cfg();
throw error;
} }
unlock_cfg(); unlock_cfg();
return true; return true;
...@@ -1686,9 +1692,15 @@ var authenticated_command_handlers = { ...@@ -1686,9 +1692,15 @@ var authenticated_command_handlers = {
if(msg_area.sub[sub]!=undefined && msg_area.sub[sub].can_read) { if(msg_area.sub[sub]!=undefined && msg_area.sub[sub].can_read) {
lock_cfg(); lock_cfg();
read_cfg(sub, false); try {
saved_config[sub].subscribed = true; read_cfg(sub, false);
save_cfg(false); saved_config[sub].subscribed = true;
save_cfg(false);
}
catch (error) {
unlock_cfg();
throw error;
}
unlock_cfg(); unlock_cfg();
tagged(tag, "OK", "Subscribed..."); tagged(tag, "OK", "Subscribed...");
} }
...@@ -1704,9 +1716,15 @@ var authenticated_command_handlers = { ...@@ -1704,9 +1716,15 @@ var authenticated_command_handlers = {
if(msg_area.sub[sub]!=undefined && msg_area.sub[sub].can_read) { if(msg_area.sub[sub]!=undefined && msg_area.sub[sub].can_read) {
lock_cfg(); lock_cfg();
read_cfg(sub, false); try {
saved_config[sub].subscribed = false; read_cfg(sub, false);
save_cfg(false); saved_config[sub].subscribed = false;
save_cfg(false);
}
catch (error) {
unlock_cfg();
throw error;
}
unlock_cfg(); unlock_cfg();
tagged(tag, "OK", "Unsubscribed..."); tagged(tag, "OK", "Unsubscribed...");
} }
...@@ -1841,64 +1859,76 @@ function do_store(seq, uid, item, data) ...@@ -1841,64 +1859,76 @@ function do_store(seq, uid, item, data)
var changed=false; var changed=false;
lock_cfg(); lock_cfg();
read_cfg(index.code, false); try {
for(i in seq) { read_cfg(index.code, false);
idx=index.idx[seq[i]]; for(i in seq) {
hdr=base.get_msg_header(seq[i], /* expand_fields: */false); idx=index.idx[seq[i]];
flags=parse_flags(data); hdr=base.get_msg_header(seq[i], /* expand_fields: */false);
switch(item.toUpperCase()) { flags=parse_flags(data);
case 'FLAGS.SILENT': switch(item.toUpperCase()) {
silent=true; case 'FLAGS.SILENT':
case 'FLAGS': silent=true;
chflags={attr:idx.attr^flags.attr, netattr:hdr.netattr^flags.netattr}; case 'FLAGS':
break; chflags={attr:idx.attr^flags.attr, netattr:hdr.netattr^flags.netattr};
case '+FLAGS.SILENT': break;
silent=true; case '+FLAGS.SILENT':
case '+FLAGS': silent=true;
chflags={attr:idx.attr^(idx.attr|flags.attr), netattr:hdr.netattr^(hdr.netattr|flags.netattr)}; case '+FLAGS':
chflags={attr:idx.attr^(idx.attr|flags.attr), netattr:hdr.netattr^(hdr.netattr|flags.netattr)};
break;
case '-FLAGS.SILENT':
silent=true;
case '-FLAGS':
chflags={attr:idx.attr^(idx.attr&~flags.attr), netattr:hdr.netattr^(hdr.netattr&~flags.netattr)};
break
}
if(chflags.attr & MSG_READ)
mod_seen=true;
chflags=check_msgflags(chflags.attr, chflags.netattr, base.subnum==-1, hdr.to_net_type==NET_NONE?hdr.to==user.number:false, hdr.from_net_type==NET_NONE?hdr.from==user.number:false,base.is_operator);
if(chflags.attr || chflags.netattr) {
hdr.attr ^= chflags.attr;
hdr.netattr ^= chflags.netattr;
if(!readonly) {
base.put_msg_header(seq[i], hdr);
changed=true;
}
}
if(!silent)
send_fetch_response(seq[i], ["FLAGS"], uid);
if (!client.socket.is_connected)
break; break;
case '-FLAGS.SILENT': js.gc();
silent=true; }
case '-FLAGS': save_cfg(false);
chflags={attr:idx.attr^(idx.attr&~flags.attr), netattr:hdr.netattr^(hdr.netattr&~flags.netattr)}; }
break catch (error) {
} unlock_cfg();
throw error;
if(chflags.attr & MSG_READ)
mod_seen=true;
chflags=check_msgflags(chflags.attr, chflags.netattr, base.subnum==-1, hdr.to_net_type==NET_NONE?hdr.to==user.number:false, hdr.from_net_type==NET_NONE?hdr.from==user.number:false,base.is_operator);
if(chflags.attr || chflags.netattr) {
hdr.attr ^= chflags.attr;
hdr.netattr ^= chflags.netattr;
if(!readonly) {
base.put_msg_header(seq[i], hdr);
changed=true;
}
}
if(!silent)
send_fetch_response(seq[i], ["FLAGS"], uid);
if (!client.socket.is_connected)
break;
js.gc();
} }
save_cfg(false);
unlock_cfg(); unlock_cfg();
if(mod_seen && base.cfg != undefined) { if(mod_seen && base.cfg != undefined) {
lock_cfg(); lock_cfg();
read_cfg(base.cfg.code, false); try {
if(saved_config[base.cfg.code] == undefined) { read_cfg(base.cfg.code, false);
saved_config[base.cfg.code] = {subscribed:false}; if(saved_config[base.cfg.code] == undefined) {
saved_config[base.cfg.code] = {subscribed:false};
}
if(saved_config[base.cfg.code].Seen == undefined) {
saved_config[base.cfg.code].Seen = {};
saved_config[base.cfg.code].Seen[header.number]=0;
}
saved_config[base.cfg.code].Seen[seq[i]] ^= 1;
if (saved_config[base.cfg.code].Seen[seq[i]])
index.idx[seq[i]].attr |= MSG_READ;
else
index.idx[seq[i]].attr &= ~MSG_READ;
save_cfg(false);
} }
if(saved_config[base.cfg.code].Seen == undefined) { catch (error) {
saved_config[base.cfg.code].Seen = {}; unlock_cfg();
saved_config[base.cfg.code].Seen[header.number]=0; throw error;
} }
saved_config[base.cfg.code].Seen[seq[i]] ^= 1;
if (saved_config[base.cfg.code].Seen[seq[i]])
index.idx[seq[i]].attr |= MSG_READ;
else
index.idx[seq[i]].attr &= ~MSG_READ;
save_cfg(false);
unlock_cfg(); unlock_cfg();
} }
if(changed) if(changed)
...@@ -2810,13 +2840,19 @@ var selected_command_handlers = { ...@@ -2810,13 +2840,19 @@ var selected_command_handlers = {
var i; var i;
lock_cfg(); lock_cfg();
read_cfg(get_base_code(base), false); try {
for(i in seq) { read_cfg(get_base_code(base), false);
send_fetch_response(seq[i], data_items, false); for(i in seq) {
if (!client.socket.is_connected) send_fetch_response(seq[i], data_items, false);
break; if (!client.socket.is_connected)
break;
}
save_cfg(false);
}
catch (error) {
unlock_cfg();
throw error;
} }
save_cfg(false);
unlock_cfg(); unlock_cfg();
js.gc(); js.gc();
tagged(tag, "OK", "There they are!"); tagged(tag, "OK", "There they are!");
...@@ -2865,14 +2901,20 @@ var selected_command_handlers = { ...@@ -2865,14 +2901,20 @@ var selected_command_handlers = {
seq=parse_seq_set(args[2],true); seq=parse_seq_set(args[2],true);
data_items=parse_data_items(args[3]); data_items=parse_data_items(args[3]);
lock_cfg(); lock_cfg();
read_cfg(get_base_code(base), false); try {
for(i in seq) { read_cfg(get_base_code(base), false);
send_fetch_response(seq[i], data_items, true); for(i in seq) {
if (!client.socket.is_connected) send_fetch_response(seq[i], data_items, true);
break; if (!client.socket.is_connected)
break;
}
save_cfg(false);
} }
save_cfg(false); catch (error) {
lock_cfg(); unlock_cfg();
throw error;
}
unlock_cfg();
js.gc(); js.gc();
tagged(tag, "OK", "There they are (with UIDs)!"); tagged(tag, "OK", "There they are (with UIDs)!");
break; break;
...@@ -2986,48 +3028,55 @@ function read_cfg(sub, lck) ...@@ -2986,48 +3028,55 @@ function read_cfg(sub, lck)
if (lck) if (lck)
lock_cfg(); lock_cfg();
if(saved_config[sub]==undefined)
saved_config[sub]={subscribed:false};
cfgfile.rewind();
contents = cfgfile.read();
try { try {
newfile = JSON.parse(contents); if(saved_config[sub]==undefined)
} saved_config[sub]={subscribed:false};
catch (error) {
newfile = {'__config_epoch__':0, mail:{scan_ptr:0, subscribed:true}}; cfgfile.rewind();
} contents = cfgfile.read();
for (newsub in newfile) { try {
if (newsub == '__config_epoch__') { newfile = JSON.parse(contents);
saved_config.__config_epoch__ = newfile[newsub];
} }
else { catch (error) {
saved_config[newsub] = {}; newfile = {'__config_epoch__':0, mail:{scan_ptr:0, subscribed:true}};
if (newfile[newsub].hasOwnProperty('seen')) }
saved_config[newsub].Seen = newfile[newsub].seen; for (newsub in newfile) {
else if (newsub == '__config_epoch__') {
saved_config[newsub].Seen = newfile[newsub].seen = {}; saved_config.__config_epoch__ = newfile[newsub];
if (newfile[newsub].hasOwnProperty('subscribed')) }
saved_config[newsub].subscribed = newfile[newsub].subscribed; else {
else saved_config[newsub] = {};
saved_config[newsub].subscribed = false; if (newfile[newsub].hasOwnProperty('seen'))
if (newfile[newsub].hasOwnProperty('bseen')) { saved_config[newsub].Seen = newfile[newsub].seen;
for (i in newfile[newsub].bseen) { else
basemsg = parseInt(i, 10); saved_config[newsub].Seen = newfile[newsub].seen = {};
bstr = base64_decode(newfile[newsub].bseen[i]); if (newfile[newsub].hasOwnProperty('subscribed'))
for (byte = 0; byte < bstr.length; byte++) { saved_config[newsub].subscribed = newfile[newsub].subscribed;
asc = ascii(bstr[byte]); else
if (asc == 0) saved_config[newsub].subscribed = false;
continue; if (newfile[newsub].hasOwnProperty('bseen')) {
for (bit=0; bit<8; bit++) { for (i in newfile[newsub].bseen) {
if (asc & (1<<bit)) basemsg = parseInt(i, 10);
saved_config[newsub].Seen[basemsg+(byte*8+bit)]=1; bstr = base64_decode(newfile[newsub].bseen[i]);
for (byte = 0; byte < bstr.length; byte++) {
asc = ascii(bstr[byte]);
if (asc == 0)
continue;
for (bit=0; bit<8; bit++) {
if (asc & (1<<bit))
saved_config[newsub].Seen[basemsg+(byte*8+bit)]=1;
}
} }
} }
} }
} }
} }
} }
catch (error) {
if (lck)
unlock_cfg();
throw error;
}
if (lck) if (lck)
unlock_cfg(); unlock_cfg();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment