diff --git a/CHANGES b/CHANGES
index 349f44ee99fbf2c48608ad8d6f4f5120d2f62159..817aa36e5a00267dc0e9424d877179c9e672b8a3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,7 @@ OpenLDAP 2.4.17 Engineering
 	Fixed slapd moduleload with static backends and modules (ITS#6016)
 	Fixed slapd normalization of updated schema attributes (ITS#5540)
 	Fixed slapd pagedresults stacked control with overlays (ITS#6056)
+	Fixed slapd sending cancelled operations results (ITS#6103)
 	Fixed slapd sockets usage on windows (ITS#6039)
 	Fixed slapd-hdb freeing of already freed entries (ITS#6074)
 	Fixed slapd-hdb entryinfo cleanup (ITS#6088)
diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c
index 09faf8ebe970d9d6796c9ea12dc98863ae7fb491..9308731e329504401afcca09a47883819f296a2b 100644
--- a/servers/slapd/back-bdb/search.c
+++ b/servers/slapd/back-bdb/search.c
@@ -668,6 +668,7 @@ loop_begin:
 		/* check for abandon */
 		if ( op->o_abandon ) {
 			rs->sr_err = SLAPD_ABANDON;
+			send_ldap_result( op, rs );
 			goto done;
 		}
 
diff --git a/servers/slapd/backglue.c b/servers/slapd/backglue.c
index b3ca5d48322e997f3a384d0736eb455339b88b80..b7bff32748e4029029f57192a522b27dd96e548b 100644
--- a/servers/slapd/backglue.c
+++ b/servers/slapd/backglue.c
@@ -535,17 +535,18 @@ end_of_loop:;
 
 		break;
 	}
+
+	op->o_callback = cb.sc_next;
 	if ( op->o_abandon ) {
 		rs->sr_err = SLAPD_ABANDON;
 	} else {
-		op->o_callback = cb.sc_next;
 		rs->sr_err = gs.err;
 		rs->sr_matched = gs.matched;
 		rs->sr_ref = gs.refs;
-		rs->sr_ctrls = gs.ctrls;
-
-		send_ldap_result( op, rs );
 	}
+	rs->sr_ctrls = gs.ctrls;
+
+	send_ldap_result( op, rs );
 
 	op->o_bd = b0;
 	op->o_bd->bd_info = bi0;
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index e63ed1a94071b16dd38f2a618be76e6f17d3c54f..4f2a7f17b12e5ea3f58ace77df8ef316ea7cf269 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -145,7 +145,7 @@ static long send_ldap_ber(
 
 	/* write only one pdu at a time - wait til it's our turn */
 	ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
-	if ( op->o_abandon || connection_state_closing( conn )) {
+	if (( op->o_abandon && !op->o_cancel ) || connection_state_closing( conn )) {
 		ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
 		return 0;
 	}
@@ -415,7 +415,7 @@ send_ldap_response(
 	int		rc = LDAP_SUCCESS;
 	long	bytes;
 
-	if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon ) {
+	if (( rs->sr_err == SLAPD_ABANDON || op->o_abandon ) && !op->o_cancel ) {
 		rc = SLAPD_ABANDON;
 		goto clean2;
 	}
@@ -437,9 +437,13 @@ send_ldap_response(
 		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
 	}
 
+	rc = rs->sr_err;
+	if ( rc == SLAPD_ABANDON && op->o_cancel )
+		rc = LDAP_CANCELLED;
+
 	Debug( LDAP_DEBUG_TRACE,
 		"send_ldap_response: msgid=%d tag=%lu err=%d\n",
-		rs->sr_msgid, rs->sr_tag, rs->sr_err );
+		rs->sr_msgid, rs->sr_tag, rc );
 
 	if( rs->sr_ref ) {
 		Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
@@ -463,7 +467,7 @@ send_ldap_response(
 
 	} else {
 	    rc = ber_printf( ber, "{it{ess" /*"}}"*/,
-		rs->sr_msgid, rs->sr_tag, rs->sr_err,
+		rs->sr_msgid, rs->sr_tag, rc,
 		rs->sr_matched == NULL ? "" : rs->sr_matched,
 		rs->sr_text == NULL ? "" : rs->sr_text );
 	}