# # patch "netsync.cc" # from [a3dd51ed7e9fa8e3379e2df516a6d338a0de5209] # to [867f233a79a22f5b46630b03c9c11e38ce14454c] # # patch "tests/t_netsync_permissions.at" # from [2e18d7f1e43cc50034a417b6ea6f18c79c5467c3] # to [cc85a9949710ba512b1c0d8d8ed4d1acca4ad3cc] # # patch "tests/t_netsync_read_permissions.at" # from [123e1ee25ec04d06cf8b221227e1456e38af732e] # to [496e7094f6ff8e9634445b6a68789438f306336c] # ======================================================================== --- netsync.cc a3dd51ed7e9fa8e3379e2df516a6d338a0de5209 +++ netsync.cc 867f233a79a22f5b46630b03c9c11e38ce14454c @@ -254,6 +254,12 @@ {} }; +struct netsync_error +{ + string msg; + netsync_error(string const & s): msg(s) {} +}; + struct session { @@ -873,22 +879,11 @@ // mode, all received data is ignored, and no new data is queued. We simply // stay connected long enough for the current write buffer to be flushed, to // ensure that our peer receives the error message. -// WARNING WARNING WARNING (FIXME): this does _not_ throw an exception. if -// while processing any given netcmd packet you encounter an error, you can -// _only_ call this method if you have not touched the database, because if -// you have touched the database then you need to throw an exception to -// trigger a rollback. -// you could, of course, call this method and then throw an exception, but -// there is no point in doing that, because throwing the exception will cause -// the connection to be immediately terminated, so your call to error() will -// actually have no effect (except to cause your error message to be printed -// twice). +// Affects read_some, write_some, and process . void session::error(std::string const & errmsg) { - W(F("error: %s\n") % errmsg); - queue_error_cmd(errmsg); - encountered_error = true; + throw netsync_error(errmsg); } @@ -2911,6 +2906,8 @@ bool session::process() { + if (encountered_error) + return true; try { if (!arm()) @@ -2933,6 +2930,13 @@ W(F("protocol error while processing peer %s: '%s'\n") % peer_id % bd.what); return false; } + catch (netsync_error & err) + { + W(F("error: %s\n") % err.msg); + queue_error_cmd(err.msg); + encountered_error = true; + return true;// don't terminate until we've send the error_cmd + } } @@ -2964,9 +2968,8 @@ } catch (bad_decode & bd) { - W(F("protocol error while processing peer %s: '%s'\n") + E(false, F("protocol error while processing peer %s: '%s'\n") % sess.peer_id % bd.what); - return; } probe.clear(); @@ -2977,8 +2980,7 @@ if (fd == -1 && !armed) { - P(F("timed out waiting for I/O with peer %s, disconnecting\n") % sess.peer_id); - return; + E(false, F("timed out waiting for I/O with peer %s, disconnecting\n") % sess.peer_id); } if (event & Netxx::Probe::ready_read) @@ -2991,9 +2993,8 @@ } catch (bad_decode & bd) { - W(F("protocol error while processing peer %s: '%s'\n") + E(false, F("protocol error while processing peer %s: '%s'\n") % sess.peer_id % bd.what); - return; } } else @@ -3001,7 +3002,7 @@ if (sess.sent_goodbye) P(F("read from fd %d (peer %s) closed OK after goodbye\n") % fd % sess.peer_id); else - P(F("read from fd %d (peer %s) failed, disconnecting\n") % fd % sess.peer_id); + E(false, F("read from fd %d (peer %s) failed, disconnecting\n") % fd % sess.peer_id); return; } } @@ -3013,23 +3014,22 @@ if (sess.sent_goodbye) P(F("write on fd %d (peer %s) closed OK after goodbye\n") % fd % sess.peer_id); else - P(F("write on fd %d (peer %s) failed, disconnecting\n") % fd % sess.peer_id); + E(false, F("write on fd %d (peer %s) failed, disconnecting\n") % fd % sess.peer_id); return; } } if (event & Netxx::Probe::ready_oobd) { - P(F("got OOB data on fd %d (peer %s), disconnecting\n") + E(false, F("got OOB data on fd %d (peer %s), disconnecting\n") % fd % sess.peer_id); - return; } if (armed) { if (!sess.process()) { - P(F("terminated exchange with %s\n") + E(false, F("terminated exchange with %s\n") % sess.peer_id); return; } ======================================================================== --- tests/t_netsync_permissions.at 2e18d7f1e43cc50034a417b6ea6f18c79c5467c3 +++ tests/t_netsync_permissions.at cc85a9949710ba512b1c0d8d8ed4d1acca4ad3cc @@ -60,7 +60,7 @@ AT_CHECK(rm -r keys2 && cp -r clean_keys/ keys2) address@hidden AT_CHECK((echo $UNKNOWN; echo $UNKNOWN) | MONOTONE2 genkey $UNKNOWN, [], [ignore], [ignore]) -NETSYNC_CLIENT_RUN(pull --key=$UNKNOWN, testbranch) +NETSYNC_CLIENT_RUN(pull --key=$UNKNOWN, testbranch, [1]) AT_CHECK(MONOTONE2 automate get_revision $BASE, [1], [stdout], [stderr]) # push with default key @@ -91,7 +91,7 @@ AT_CHECK(MONOTONE2 commit --message unknown, [], [ignore], [ignore]) UNKNOWN_REV=`BASE_REVISION` AT_CHECK((echo $UNKNOWN; echo $UNKNOWN) | MONOTONE2 genkey $UNKNOWN, [], [ignore], [ignore]) -NETSYNC_CLIENT_RUN(push --key=$UNKNOWN, testbranch) +NETSYNC_CLIENT_RUN(push --key=$UNKNOWN, testbranch, [1]) NETSYNC_SERVE_STOP @@ -129,7 +129,7 @@ AT_CHECK(cp clean.db test2.db) AT_CHECK(rm -r keys2 && cp -r clean_keys/ keys2) -NETSYNC_CLIENT_RUN(pull --key="", testbranch) +NETSYNC_CLIENT_RUN(pull --key="", testbranch, [1]) AT_CHECK(MONOTONE2 automate get_revision $BASE, [1], [stdout], [stderr]) # pull with default key @@ -143,7 +143,7 @@ AT_CHECK(cp clean.db test2.db) AT_CHECK(rm -r keys2 && cp -r clean_keys/ keys2) -NETSYNC_CLIENT_RUN(pull --key=$OTHER, testbranch) +NETSYNC_CLIENT_RUN(pull --key=$OTHER, testbranch, [1]) AT_CHECK(MONOTONE2 automate get_revision $BASE, [1], [stdout], [stderr]) # pull with unknown key fails @@ -152,7 +152,7 @@ AT_CHECK(rm -r keys2 && cp -r clean_keys/ keys2) address@hidden AT_CHECK((echo $UNKNOWN; echo $UNKNOWN) | MONOTONE2 genkey $UNKNOWN, [], [ignore], [ignore]) -NETSYNC_CLIENT_RUN(pull --key=$UNKNOWN, testbranch) +NETSYNC_CLIENT_RUN(pull --key=$UNKNOWN, testbranch, [1]) AT_CHECK(MONOTONE2 automate get_revision $BASE, [1], [stdout], [stderr]) # push with default key @@ -173,7 +173,7 @@ ]) AT_CHECK(MONOTONE2 commit --message other, [], [ignore], [ignore]) OTHER_REV=`BASE_REVISION` -NETSYNC_CLIENT_RUN(push --key=$OTHER, testbranch) +NETSYNC_CLIENT_RUN(push --key=$OTHER, testbranch, [1]) # push with unknown key fails @@ -183,7 +183,7 @@ AT_CHECK(MONOTONE2 commit --message unknown, [], [ignore], [ignore]) UNKNOWN_REV=`BASE_REVISION` AT_CHECK((echo $UNKNOWN; echo $UNKNOWN) | MONOTONE2 genkey $UNKNOWN, [], [ignore], [ignore]) -NETSYNC_CLIENT_RUN(push --key=$UNKNOWN, testbranch) +NETSYNC_CLIENT_RUN(push --key=$UNKNOWN, testbranch, [1]) NETSYNC_SERVE_STOP ======================================================================== --- tests/t_netsync_read_permissions.at 123e1ee25ec04d06cf8b221227e1456e38af732e +++ tests/t_netsync_read_permissions.at 496e7094f6ff8e9634445b6a68789438f306336c @@ -36,7 +36,7 @@ NETSYNC_SERVE_START(--rcfile=limited_permission.at 'branch*') -NETSYNC_CLIENT_RUN(pull, 'branch*') +NETSYNC_CLIENT_RUN(pull, 'branch*', [1]) AT_CHECK(MONOTONE2 automate get_revision $B1, [1], [ignore], [ignore]) AT_CHECK(MONOTONE2 automate get_revision $B2, [1], [ignore], [ignore]) AT_CHECK(MONOTONE2 automate get_revision $B3, [1], [ignore], [ignore])