Browse Source

When an async operation dies, orphan its children.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
8bb9f726a0
1 changed files with 74 additions and 35 deletions
  1. 74
    35
      src/core/async.c

+ 74
- 35
src/core/async.c View File

@@ -125,8 +125,15 @@ aid_t async_init ( struct async *async, struct async_operations *aop,
125 125
  * async).
126 126
  */
127 127
 void async_uninit ( struct async *async ) {
128
-	if ( async->parent )
128
+
129
+	assert ( async != NULL );
130
+
131
+	if ( async->parent ) {
132
+		assert ( list_empty ( &async->children ) );
133
+
134
+		DBGC ( async, "ASYNC %p uninitialising\n", async );
129 135
 		list_del ( &async->siblings );
136
+	}
130 137
 }
131 138
 
132 139
 /**
@@ -237,6 +244,51 @@ void async_signal_children ( struct async *async, enum signal signal ) {
237 244
 	}
238 245
 }
239 246
 
247
+/**
248
+ * Reap default handler
249
+ *
250
+ * @v async		Asynchronous operation
251
+ */
252
+static void async_reap_default ( struct async *async ) {
253
+
254
+	DBGC ( async, "ASYNC %p ignoring REAP\n", async );
255
+
256
+	assert ( async != NULL );
257
+
258
+	/* Nothing to do */
259
+}
260
+
261
+/**
262
+ * Reap asynchronous operation
263
+ *
264
+ * @v async		Asynchronous operation
265
+ *
266
+ * Note that the asynchronous operation should have been freed by
267
+ * calling this function; you may not dereference @c async after this
268
+ * call.
269
+ */
270
+static void async_reap ( struct async *async ) {
271
+
272
+	DBGC ( async, "ASYNC %p being reaped, exit status %d (%s)\n",
273
+	       async, async->rc, strerror ( async->rc ) );
274
+
275
+	assert ( async != NULL );
276
+	assert ( async->aop != NULL );
277
+	assert ( list_empty ( &async->children ) );
278
+
279
+	/* Unlink from hierarchy */
280
+	if ( async->parent )
281
+		list_del ( &async->siblings );
282
+	async->parent = NULL;
283
+
284
+	/* Release all resources */
285
+	if ( async->aop->reap ) {
286
+		async->aop->reap ( async );
287
+	} else {
288
+		async_reap_default ( async );
289
+	}
290
+}
291
+
240 292
 /**
241 293
  * Mark asynchronous operation as complete
242 294
  *
@@ -248,6 +300,8 @@ void async_signal_children ( struct async *async, enum signal signal ) {
248 300
  * having its reap() method called.
249 301
  */
250 302
 void async_done ( struct async *async, int rc ) {
303
+	struct async *child;
304
+	struct async *tmp;
251 305
 
252 306
 	DBGC ( async, "ASYNC %p completing with status %d (%s)\n",
253 307
 	       async, rc, strerror ( rc ) );
@@ -259,23 +313,22 @@ void async_done ( struct async *async, int rc ) {
259 313
 	/* Store return status code */
260 314
 	async->rc = rc;
261 315
 
262
-	/* Send SIGCHLD to parent.  Guard against NULL pointer dereferences */
263
-	if ( async->parent )
264
-		async_signal ( async->parent, SIGCHLD );
265
-}
266
-
267
-/**
268
- * Reap default handler
269
- *
270
- * @v async		Asynchronous operation
271
- */
272
-static void async_reap_default ( struct async *async ) {
273
-
274
-	DBGC ( async, "ASYNC %p ignoring REAP\n", async );
275
-
276
-	assert ( async != NULL );
316
+	/* Disown all of our children */
317
+	list_for_each_entry_safe ( child, tmp, &async->children, siblings ) {
318
+		DBGC ( async, "ASYNC %p disowning child ASYNC %p\n",
319
+		       async, child );
320
+		list_del ( &child->siblings );
321
+		child->parent = NULL;
322
+	}
277 323
 
278
-	/* Nothing to do */
324
+	/* Send SIGCHLD to parent.  If we don't have a parent then we
325
+	 * have to take care of our own funeral arrangements.
326
+	 */
327
+	if ( async->parent ) {
328
+		async_signal ( async->parent, SIGCHLD );
329
+	} else {
330
+		async_reap ( async );
331
+	}
279 332
 }
280 333
 
281 334
 /**
@@ -319,25 +372,11 @@ aid_t async_wait ( struct async *async, int *rc, int block ) {
319 372
 			*rc = child->rc;
320 373
 			child_aid = child->aid;
321 374
 
322
-			DBGC ( async, "ASYNC %p reaping child ASYNC %p (ID "
323
-			       "%ld), exit status %d (%s)\n", async, child,
324
-			       child_aid, child->rc, strerror ( child->rc ) );
325
-
326
-			/* Reap the child */
327
-			assert ( child->aop != NULL );
328
-			assert ( list_empty ( &child->children ) );
329
-
330
-			/* Unlink from operations hierarchy */
331
-			list_del ( &child->siblings );
332
-			child->parent = NULL;
333
-
334
-			/* Release all resources */
335
-			if ( child->aop->reap ) {
336
-				child->aop->reap ( child );
337
-			} else {
338
-				async_reap_default ( child );
339
-			}
375
+			DBGC ( async, "ASYNC %p reaping child ASYNC %p "
376
+			       "(ID %ld)\n", async, child, child_aid );
340 377
 
378
+			/* Reap the child and return */
379
+			async_reap ( child );
341 380
 			return child_aid;
342 381
 		}
343 382
 

Loading…
Cancel
Save