|  | @@ -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 |  
 |