125 lines
3.3 KiB
Diff
125 lines
3.3 KiB
Diff
From 5f934c8c457ffe906c844ab2313943ae9b66bc46 Mon Sep 17 00:00:00 2001
|
|
From: Howard Chu <hyc@openldap.org>
|
|
Date: Mon, 27 Feb 2023 15:01:23 +0000
|
|
Subject: [PATCH] ITS#10016: slapo-syncprov: fix Abandon with active qtask
|
|
|
|
---
|
|
servers/slapd/overlays/syncprov.c | 42 ++++++++++++++++++++++++++-----
|
|
1 file changed, 36 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c
|
|
index f62d6c63ea..44a6181410 100644
|
|
--- a/servers/slapd/overlays/syncprov.c
|
|
+++ b/servers/slapd/overlays/syncprov.c
|
|
@@ -871,6 +871,11 @@ static void free_resinfo( syncres *sr )
|
|
|
|
#define FS_UNLINK 1
|
|
#define FS_LOCK 2
|
|
+#define FS_DEFER 4
|
|
+
|
|
+#define FSR_NOTFREE 0
|
|
+#define FSR_DIDFREE 1
|
|
+#define FSR_CANFREE 2
|
|
|
|
static int
|
|
syncprov_free_syncop( syncops *so, int flags )
|
|
@@ -881,12 +886,19 @@ syncprov_free_syncop( syncops *so, int flags )
|
|
if ( flags & FS_LOCK )
|
|
ldap_pvt_thread_mutex_lock( &so->s_mutex );
|
|
/* already being freed, or still in use */
|
|
- if ( !so->s_inuse || --so->s_inuse > 0 ) {
|
|
+ if ( !so->s_inuse || so->s_inuse > 1 ) {
|
|
if ( flags & FS_LOCK )
|
|
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
|
|
- return 0;
|
|
+ if ( !( flags & FS_DEFER ) && so->s_inuse )
|
|
+ so->s_inuse--;
|
|
+ return FSR_NOTFREE;
|
|
}
|
|
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
|
|
+
|
|
+ /* caller wants to cleanup other stuff before actual free */
|
|
+ if ( flags & FS_DEFER )
|
|
+ return FSR_CANFREE;
|
|
+
|
|
if (( flags & FS_UNLINK ) && so->s_si ) {
|
|
syncops **sop;
|
|
ldap_pvt_thread_mutex_lock( &so->s_si->si_ops_mutex );
|
|
@@ -914,7 +926,7 @@ syncprov_free_syncop( syncops *so, int flags )
|
|
}
|
|
ldap_pvt_thread_mutex_destroy( &so->s_mutex );
|
|
ch_free( so );
|
|
- return 1;
|
|
+ return FSR_DIDFREE;
|
|
}
|
|
|
|
/* Send a persistent search response */
|
|
@@ -1029,6 +1041,9 @@ syncprov_qplay( Operation *op, syncops *so )
|
|
} else {
|
|
rc = syncprov_sendresp( op, sr->s_info, so, sr->s_mode );
|
|
}
|
|
+ } else {
|
|
+ /* set rc so we don't do a new qstart */
|
|
+ rc = 1;
|
|
}
|
|
|
|
free_resinfo( sr );
|
|
@@ -1055,6 +1070,9 @@ syncprov_qplay( Operation *op, syncops *so )
|
|
return rc;
|
|
}
|
|
|
|
+static int
|
|
+syncprov_drop_psearch( syncops *so, int lock );
|
|
+
|
|
/* task for playing back queued responses */
|
|
static void *
|
|
syncprov_qtask( void *ctx, void *arg )
|
|
@@ -1063,7 +1081,7 @@ syncprov_qtask( void *ctx, void *arg )
|
|
OperationBuffer opbuf;
|
|
Operation *op;
|
|
BackendDB be;
|
|
- int rc;
|
|
+ int rc, flag, frc;
|
|
|
|
op = &opbuf.ob_op;
|
|
*op = *so->s_op;
|
|
@@ -1092,14 +1110,24 @@ syncprov_qtask( void *ctx, void *arg )
|
|
if ( !rc && !so->s_res )
|
|
rc = 1;
|
|
|
|
+ flag = FS_UNLINK;
|
|
+ if ( rc && op->o_abandon )
|
|
+ flag = FS_DEFER;
|
|
+
|
|
/* decrement use count... */
|
|
- if ( !syncprov_free_syncop( so, FS_UNLINK )) {
|
|
+ frc = syncprov_free_syncop( so, flag );
|
|
+ if ( frc == FSR_NOTFREE ) {
|
|
if ( rc )
|
|
/* if we didn't unlink, and task is no longer queued, clear flag */
|
|
so->s_flags ^= PS_TASK_QUEUED;
|
|
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
|
|
}
|
|
|
|
+ /* if we got abandoned while processing, cleanup now */
|
|
+ if ( frc == FSR_CANFREE ) {
|
|
+ syncprov_drop_psearch( so, 1 );
|
|
+ }
|
|
+
|
|
return NULL;
|
|
}
|
|
|
|
@@ -1274,7 +1302,9 @@ syncprov_op_abandon( Operation *op, SlapReply *rs )
|
|
return SLAP_CB_CONTINUE;
|
|
}
|
|
}
|
|
- syncprov_drop_psearch( so, 0 );
|
|
+ /* if task is active, it must drop itself */
|
|
+ if ( !( so->s_flags & PS_TASK_QUEUED ))
|
|
+ syncprov_drop_psearch( so, 0 );
|
|
}
|
|
return SLAP_CB_CONTINUE;
|
|
}
|
|
--
|
|
GitLab
|