static void scope_realize(GtkWidget *widget) { Scope *scope; GdkWindowAttr attributes; gint attributes_mask; GdkGCValues gc_values; GtkAllocation allocation; GdkWindow *window; GtkStyle *style; g_return_if_fail(widget != NULL); g_return_if_fail(IS_SCOPE(widget)); scope = SCOPE(widget); gtk_widget_set_realized(widget, TRUE); gtk_widget_get_allocation(widget, &allocation); attributes.window_type = GDK_WINDOW_CHILD; attributes.x = allocation.x; attributes.y = allocation.y; attributes.width = allocation.width; attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual(widget); attributes.colormap = gtk_widget_get_colormap(widget); attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; gtk_widget_set_has_window(widget, TRUE); window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask); gtk_widget_set_window(widget, window); gdk_window_set_user_data(window, scope); gtk_widget_style_attach(widget); style = gtk_widget_get_style(widget); gtk_style_set_background(style, window, GTK_STATE_NORMAL); /* gc's if necessary */ if (!gdk_colormap_alloc_color(style->colormap, &scope->tracecol, FALSE, TRUE)) g_warning("unable to allocate color: ( %d %d %d )", scope->tracecol.red, scope->tracecol.green, scope->tracecol.blue); gc_values.foreground = scope->tracecol; scope->trace_gc = gtk_gc_get(style->depth, style->colormap, &gc_values, GDK_GC_FOREGROUND); if (!gdk_colormap_alloc_color(style->colormap, &scope->gridcol, FALSE, TRUE)) g_warning("unable to allocate color: ( %d %d %d )", scope->gridcol.red, scope->gridcol.green, scope->gridcol.blue); gc_values.foreground = scope->gridcol; scope->grid_gc = gtk_gc_get(style->depth, style->colormap, &gc_values, GDK_GC_FOREGROUND); /* create backing store */ scope->pixmap = gdk_pixmap_new(window, SCOPE_WIDTH, SCOPE_HEIGHT, -1); scope_send_configure(SCOPE(widget)); }
static gint idle_callback(gpointer data) { g_return_val_if_fail(data != NULL, FALSE); g_return_val_if_fail(IS_SCOPE(data), FALSE); SCOPE(data)->idlefunc = 0; if (!gtk_widget_is_drawable(GTK_WIDGET(data))) return FALSE; draw(SCOPE(data)); return FALSE; /* don't call this callback again */ }
static int scope_load_init_scope(Unit *u) { assert(u); if (!unit_has_name(u, SPECIAL_INIT_SCOPE)) return 0; u->transient = true; u->perpetual = true; /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we * synthesize it here, instead of relying on the unit file on disk. */ u->default_dependencies = false; u->ignore_on_isolate = true; SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14; /* Prettify things, if we can. */ if (!u->description) u->description = strdup("System and Service Manager"); if (!u->documentation) (void) strv_extend(&u->documentation, "man:systemd(1)"); return 1; }
static int scope_load(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); assert(u->load_state == UNIT_STUB); if (!u->transient && !manager_is_reloading_or_reexecuting(u->manager)) return -ENOENT; u->load_state = UNIT_LOADED; r = unit_load_dropin(u); if (r < 0) return r; r = unit_patch_contexts(u); if (r < 0) return r; r = unit_set_default_slice(u); if (r < 0) return r; r = scope_add_default_dependencies(s); if (r < 0) return r; return scope_verify(s); }
static int scope_start(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); if (s->state == SCOPE_FAILED) return -EPERM; if (s->state == SCOPE_STOP_SIGTERM || s->state == SCOPE_STOP_SIGKILL) return -EAGAIN; assert(s->state == SCOPE_DEAD); if (!u->transient && UNIT(s)->manager->n_reloading <= 0) return -ENOENT; r = unit_realize_cgroup(u); if (r < 0) { log_error("Failed to realize cgroup: %s", strerror(-r)); return r; } r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, UNIT(s)->pids); if (r < 0) return r; s->result = SCOPE_SUCCESS; scope_set_state(s, SCOPE_RUNNING); return 0; }
static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Scope *s = SCOPE(u); assert(u); assert(key); assert(value); assert(fds); if (streq(key, "state")) { ScopeState state; state = scope_state_from_string(value); if (state < 0) log_unit_debug(u, "Failed to parse state value: %s", value); else s->deserialized_state = state; } else if (streq(key, "was-abandoned")) { int k; k = parse_boolean(value); if (k < 0) log_unit_debug(u, "Failed to parse boolean value: %s", value); else s->was_abandoned = k; } else log_unit_debug(u, "Unknown serialization key: %s", key); return 0; }
static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { Scope *s = SCOPE(userdata); assert(s); assert(s->timer_event_source == source); switch (s->state) { case SCOPE_STOP_SIGTERM: if (s->kill_context.send_sigkill) { log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id); scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT); } else { log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id); scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); } break; case SCOPE_STOP_SIGKILL: log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id); scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); break; default: assert_not_reached("Timeout at wrong time."); } return 0; }
static int scope_start(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); if (s->state == SCOPE_FAILED) return -EPERM; /* We can't fulfill this right now, please try again later */ if (s->state == SCOPE_STOP_SIGTERM || s->state == SCOPE_STOP_SIGKILL) return -EAGAIN; assert(s->state == SCOPE_DEAD); if (!u->transient && UNIT(s)->manager->n_reloading <= 0) return -ENOENT; (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); r = unit_attach_pids_to_cgroup(u); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); return r; } s->result = SCOPE_SUCCESS; scope_set_state(s, SCOPE_RUNNING); return 1; }
static int scope_load(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); assert(u->load_state == UNIT_STUB); if (!u->transient && UNIT(s)->manager->n_reloading <= 0) return -ENOENT; u->load_state = UNIT_LOADED; r = unit_load_dropin(u); if (r < 0) return r; r = unit_add_default_slice(u); if (r < 0) return r; if (u->default_dependencies) { r = scope_add_default_dependencies(s); if (r < 0) return r; } return scope_verify(s); }
int bus_scope_set_property( Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error) { Scope *s = SCOPE(u); int r; assert(s); assert(name); assert(message); r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error); if (r != 0) return r; if (u->load_state == UNIT_STUB) { /* While we are created we still accept PIDs */ r = bus_scope_set_transient_property(s, name, message, mode, error); if (r != 0) return r; r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error); if (r != 0) return r; } return 0; }
static int scope_load(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); assert(u->load_state == UNIT_STUB); if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) /* Refuse to load non-transient scope units, but allow them while reloading. */ return -ENOENT; r = scope_load_init_scope(u); if (r < 0) return r; r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; if (u->load_state == UNIT_LOADED) { r = unit_patch_contexts(u); if (r < 0) return r; r = unit_set_default_slice(u); if (r < 0) return r; r = scope_add_default_dependencies(s); if (r < 0) return r; } return scope_verify(s); }
static void scope_enumerate_perpetual(Manager *m) { Unit *u; int r; assert(m); /* Let's unconditionally add the "init.scope" special unit * that encapsulates PID 1. Note that PID 1 already is in the * cgroup for this, we hence just need to allocate the object * for it and that's it. */ u = manager_get_unit(m, SPECIAL_INIT_SCOPE); if (!u) { r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u); if (r < 0) { log_error_errno(r, "Failed to allocate the special " SPECIAL_INIT_SCOPE " unit: %m"); return; } } u->transient = true; u->perpetual = true; SCOPE(u)->deserialized_state = SCOPE_RUNNING; unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); }
static void scope_enumerate(Manager *m) { Unit *u; int r; assert(m); /* Let's unconditionally add the "init.scope" special unit * that encapsulates PID 1. Note that PID 1 already is in the * cgroup for this, we hence just need to allocate the object * for it and that's it. */ u = manager_get_unit(m, SPECIAL_INIT_SCOPE); if (!u) { u = unit_new(m, sizeof(Scope)); if (!u) { log_oom(); return; } r = unit_add_name(u, SPECIAL_INIT_SCOPE); if (r < 0) { unit_free(u); log_error_errno(r, "Failed to add init.scope name"); return; } } u->transient = true; u->default_dependencies = false; u->no_gc = true; u->ignore_on_isolate = true; u->refuse_manual_start = true; u->refuse_manual_stop = true; SCOPE(u)->deserialized_state = SCOPE_RUNNING; SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14; /* Prettify things, if we can. */ if (!u->description) u->description = strdup("System and Service Manager"); if (!u->documentation) (void) strv_extend(&u->documentation, "man:systemd(1)"); unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); }
static void scope_notify_cgroup_empty_event(Unit *u) { Scope *s = SCOPE(u); assert(u); log_unit_debug(u, "cgroup is empty"); if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) scope_enter_dead(s, SCOPE_SUCCESS); }
static void scope_init(Unit *u) { Scope *s = SCOPE(u); assert(u); assert(u->load_state == UNIT_STUB); s->timeout_stop_usec = u->manager->default_timeout_stop_usec; u->ignore_on_isolate = true; }
static void scope_done(Unit *u) { Scope *s = SCOPE(u); assert(u); free(s->controller); s->timer_event_source = sd_event_source_unref(s->timer_event_source); }
static void scope_reset_failed(Unit *u) { Scope *s = SCOPE(u); assert(s); if (s->state == SCOPE_FAILED) scope_set_state(s, SCOPE_DEAD); s->result = SCOPE_SUCCESS; }
static int scope_serialize(Unit *u, FILE *f, FDSet *fds) { Scope *s = SCOPE(u); assert(s); assert(f); assert(fds); unit_serialize_item(u, f, "state", scope_state_to_string(s->state)); return 0; }
static void scope_done(Unit *u) { Scope *s = SCOPE(u); assert(u); cgroup_context_done(&s->cgroup_context); set_free(s->pids); s->pids = NULL; s->timer_event_source = sd_event_source_unref(s->timer_event_source); }
static int scope_get_timeout(Unit *u, uint64_t *timeout) { Scope *s = SCOPE(u); int r; if (!s->timer_event_source) return 0; r = sd_event_source_get_time(s->timer_event_source, timeout); if (r < 0) return r; return 1; }
static int scope_stop(Unit *u) { Scope *s = SCOPE(u); assert(s); if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) return 0; assert(IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED)); scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS); return 1; }
static gint scope_expose(GtkWidget *widget, GdkEventExpose *event) { Scope *scope; g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(IS_SCOPE(widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (gtk_widget_is_drawable(widget)) { scope = SCOPE(widget); if (!scope->idlefunc) scope->idlefunc = g_idle_add_full(PRIO, idle_callback, scope, NULL); } return FALSE; }
static gint scope_expose(GtkWidget *widget, GdkEventExpose *event) { Scope *scope; g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(IS_SCOPE(widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (GTK_WIDGET_DRAWABLE(widget)) { scope = SCOPE(widget); if (!scope->idlefunc) scope->idlefunc = gtk_idle_add_priority(PRIO, idle_callback, scope); } return FALSE; }
static void scope_init(Unit *u) { Scope *s = SCOPE(u); assert(u); assert(u->load_state == UNIT_STUB); s->timeout_stop_usec = u->manager->default_timeout_stop_usec; cgroup_context_init(&s->cgroup_context); kill_context_init(&s->kill_context); UNIT(s)->ignore_on_isolate = true; UNIT(s)->ignore_on_snapshot = true; }
static int scope_serialize(Unit *u, FILE *f, FDSet *fds) { Scope *s = SCOPE(u); assert(s); assert(f); assert(fds); unit_serialize_item(u, f, "state", scope_state_to_string(s->state)); unit_serialize_item(u, f, "was-abandoned", yes_no(s->was_abandoned)); if (s->controller) unit_serialize_item(u, f, "controller", s->controller); return 0; }
static void scope_dump(Unit *u, FILE *f, const char *prefix) { Scope *s = SCOPE(u); assert(s); assert(f); fprintf(f, "%sScope State: %s\n" "%sResult: %s\n", prefix, scope_state_to_string(s->state), prefix, scope_result_to_string(s->result)); cgroup_context_dump(&s->cgroup_context, f, prefix); kill_context_dump(&s->kill_context, f, prefix); }
static int scope_stop(Unit *u) { Scope *s = SCOPE(u); assert(s); assert(s->state == SCOPE_RUNNING); if (s->state == SCOPE_STOP_SIGTERM || s->state == SCOPE_STOP_SIGKILL) return 0; assert(s->state == SCOPE_RUNNING); scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS); return 0; }
static int scope_start(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); if (unit_has_name(u, SPECIAL_INIT_SCOPE)) return -EPERM; if (s->state == SCOPE_FAILED) return -EPERM; /* We can't fulfill this right now, please try again later */ if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) return -EAGAIN; assert(s->state == SCOPE_DEAD); if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) return -ENOENT; (void) bus_scope_track_controller(s); r = unit_acquire_invocation_id(u); if (r < 0) return r; (void) unit_realize_cgroup(u); (void) unit_reset_cpu_accounting(u); (void) unit_reset_ip_accounting(u); unit_export_state_files(UNIT(s)); r = unit_attach_pids_to_cgroup(u, UNIT(s)->pids, NULL); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m"); scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); return r; } s->result = SCOPE_SUCCESS; scope_set_state(s, SCOPE_RUNNING); /* Start watching the PIDs currently in the scope */ (void) unit_enqueue_rewatch_pids(UNIT(s)); return 1; }
static int scope_get_timeout(Unit *u, usec_t *timeout) { Scope *s = SCOPE(u); usec_t t; int r; if (!s->timer_event_source) return 0; r = sd_event_source_get_time(s->timer_event_source, &t); if (r < 0) return r; if (t == USEC_INFINITY) return 0; *timeout = t; return 1; }
static bool scope_check_gc(Unit *u) { Scope *s = SCOPE(u); int r; assert(s); /* Never clean up scopes that still have a process around, * even if the scope is formally dead. */ if (UNIT(s)->cgroup_path) { r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true); if (r <= 0) return true; } return false; }