static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Operation *o = userdata; int r; assert(o); assert(si); log_debug("Operating " PID_FMT " is now complete with code=%s status=%i", o->pid, sigchld_code_to_string(si->si_code), si->si_status); o->pid = 0; if (si->si_code != CLD_EXITED) { r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally."); goto fail; } if (si->si_status == EXIT_SUCCESS) r = 0; else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */ r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed."); goto fail; } if (o->done) { /* A completion routine is set for this operation, call it. */ r = o->done(o, r, &error); if (r < 0) { if (!sd_bus_error_is_set(&error)) sd_bus_error_set_errno(&error, r); goto fail; } } else { /* The default operation when done is to simply return an error on failure or an empty success * message on success. */ if (r < 0) { sd_bus_error_set_errno(&error, r); goto fail; } r = sd_bus_reply_method_return(o->message, NULL); if (r < 0) log_error_errno(r, "Failed to reply to message: %m"); } operation_free(o); return 0; fail: r = sd_bus_reply_method_error(o->message, &error); if (r < 0) log_error_errno(r, "Failed to reply to message: %m"); operation_free(o); return 0; }
void manager_free(Manager *m) { Machine *machine; assert(m); while (m->operations) operation_free(m->operations); assert(m->n_operations == 0); while ((machine = hashmap_first(m->machines))) machine_free(machine); hashmap_free(m->machines); hashmap_free(m->machine_units); hashmap_free(m->machine_leaders); hashmap_free_with_destructor(m->image_cache, image_unref); sd_event_source_unref(m->image_cache_defer_event); bus_verify_polkit_async_registry_free(m->polkit_registry); sd_bus_unref(m->bus); sd_event_unref(m->event); free(m); }
/* * Thread routine for sending search results to a client * which is persistently waiting for them. * * This routine will terminate when either (a) the ps_complete * flag is set, or (b) the associated operation is abandoned. * In any case, the thread won't notice until it wakes from * sleeping on the ps_list condition variable, so it needs * to be awakened. */ static void ps_send_results( void *arg ) { PSearch *ps = (PSearch *)arg; PSEQNode *peq, *peqnext; struct slapi_filter *filter = 0; char *base = NULL; Slapi_DN *sdn = NULL; char *fstr = NULL; char **pbattrs = NULL; int conn_acq_flag = 0; g_incr_active_threadcnt(); /* need to acquire a reference to this connection so that it will not be released or cleaned up out from under us */ PR_Lock( ps->ps_pblock->pb_conn->c_mutex ); conn_acq_flag = connection_acquire_nolock(ps->ps_pblock->pb_conn); PR_Unlock( ps->ps_pblock->pb_conn->c_mutex ); if (conn_acq_flag) { slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d Could not acquire the connection - psearch aborted\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid); } PR_Lock( psearch_list->pl_cvarlock ); while ( (conn_acq_flag == 0) && !ps->ps_complete ) { /* Check for an abandoned operation */ if ( ps->ps_pblock->pb_op == NULL || slapi_op_abandoned( ps->ps_pblock ) ) { slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d The operation has been abandoned\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid); break; } if ( NULL == ps->ps_eq_head ) { /* Nothing to do */ PR_WaitCondVar( psearch_list->pl_cvar, PR_INTERVAL_NO_TIMEOUT ); } else { /* dequeue the item */ int attrsonly; char **attrs; LDAPControl **ectrls; Slapi_Entry *ec; Slapi_Filter *f = NULL; PR_Lock( ps->ps_lock ); peq = ps->ps_eq_head; ps->ps_eq_head = peq->pe_next; if ( NULL == ps->ps_eq_head ) { ps->ps_eq_tail = NULL; } PR_Unlock( ps->ps_lock ); /* Get all the information we need to send the result */ ec = peq->pe_entry; slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRS, &attrs ); slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRSONLY, &attrsonly ); if ( !ps->ps_send_entchg_controls || peq->pe_ctrls[0] == NULL ) { ectrls = NULL; } else { ectrls = peq->pe_ctrls; } /* * Send the result. Since send_ldap_search_entry can block for * up to 30 minutes, we relinquish all locks before calling it. */ PR_Unlock(psearch_list->pl_cvarlock); /* * The entry is in the right scope and matches the filter * but we need to redo the filter test here to check access * controls. See the comments at the slapi_filter_test() * call in ps_service_persistent_searches(). */ slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_FILTER, &f ); /* See if the entry meets the filter and ACL criteria */ if ( slapi_vattr_filter_test( ps->ps_pblock, ec, f, 1 /* verify_access */ ) == 0 ) { int rc = 0; slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_RESULT_ENTRY, ec ); rc = send_ldap_search_entry( ps->ps_pblock, ec, ectrls, attrs, attrsonly ); if (rc) { slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d Error %d sending entry %s with op status %d\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid, rc, slapi_entry_get_dn_const(ec), ps->ps_pblock->pb_op->o_status); } } PR_Lock(psearch_list->pl_cvarlock); /* Deallocate our wrapper for this entry */ pe_ch_free( &peq ); } } PR_Unlock( psearch_list->pl_cvarlock ); ps_remove( ps ); /* indicate the end of search */ plugin_call_plugins( ps->ps_pblock , SLAPI_PLUGIN_POST_SEARCH_FN ); /* free things from the pblock that were not free'd in do_search() */ /* we strdup'd this in search.c - need to free */ slapi_pblock_get( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, &base ); slapi_pblock_set( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, NULL ); slapi_ch_free_string(&base); /* Free SLAPI_SEARCH_* before deleting op since those are held by op */ slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, &sdn ); slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, NULL ); slapi_sdn_free(&sdn); slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_STRFILTER, &fstr ); slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_STRFILTER, NULL ); slapi_ch_free_string(&fstr); slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRS, &pbattrs ); slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_ATTRS, NULL ); if ( pbattrs != NULL ) { charray_free( pbattrs ); } slapi_pblock_get(ps->ps_pblock, SLAPI_SEARCH_FILTER, &filter ); slapi_pblock_set(ps->ps_pblock, SLAPI_SEARCH_FILTER, NULL ); slapi_filter_free(filter, 1); /* Clean up the connection structure */ PR_Lock( ps->ps_pblock->pb_conn->c_mutex ); slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d Releasing the connection and operation\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid); /* Delete this op from the connection's list */ connection_remove_operation( ps->ps_pblock->pb_conn, ps->ps_pblock->pb_op ); operation_free(&(ps->ps_pblock->pb_op),ps->ps_pblock->pb_conn); ps->ps_pblock->pb_op=NULL; /* Decrement the connection refcnt */ if (conn_acq_flag == 0) { /* we acquired it, so release it */ connection_release_nolock (ps->ps_pblock->pb_conn); } PR_Unlock( ps->ps_pblock->pb_conn->c_mutex ); PR_DestroyLock ( ps->ps_lock ); ps->ps_lock = NULL; slapi_ch_free((void **) &ps->ps_pblock ); for ( peq = ps->ps_eq_head; peq; peq = peqnext) { peqnext = peq->pe_next; pe_ch_free( &peq ); } slapi_ch_free((void **) &ps ); g_decr_active_threadcnt(); }