📄 process.c
字号:
return process->block_table; }static StackStash *get_stack_stash (MPProcess *process){ if (!process->stack_stash) process->stack_stash = stack_stash_new (); return process->stack_stash;}voidprocess_exec_reset (MPProcess *process){ process_reinit (process); g_signal_emit_by_name (process, "reset");}static voidprocess_command (MPProcess *process, MIInfo *info, StackElement *stack){ GHashTable *block_table; Block *block; static lont int max_use = 0; if (info->any.seqno != process->seqno) { queue_command (process, info, stack); return; } process->seqno++; block = NULL; switch (info->operation) { case MI_NEW: case MI_FORK: case MI_CLONE: case MI_EXEC: g_assert_not_reached (); break; case MI_EXIT: /* Handled before, ignore */ break; default: /* MALLOC / REALLOC / FREE */ block_table = get_block_table (process); if (info->alloc.old_ptr != NULL) { block = g_hash_table_lookup (block_table, info->alloc.old_ptr); if (!block) { g_warning ("Block %p not found (pid=%d)!\n", info->alloc.old_ptr, process->pid); process_dump_stack (process, stderr, stack); } else { g_hash_table_remove (block_table, info->alloc.old_ptr); process->bytes_used -= block->size; block_unref (block); process->n_allocations--; } } /* We need to lookup before inserting, because realloc() can call malloc(), so we * see the same block twice. The same problem comes upduring malloc initialization * where __libc_malloc() is called twice for the same block. We could optimize * things a bit by using g_hash_table_new_full() to catch the replacement when * it happens and free the old block, but that would make keeping track of * process->n_allocations/bytes_used a little difficult. */ if (info->alloc.new_ptr && !g_hash_table_lookup (block_table, info->alloc.new_ptr)) { block = g_new (Block, 1); block->refcount = 1; block->flags = 0; block->addr = info->alloc.new_ptr; block->size = info->alloc.size; block->stack = stack; process->n_allocations++; process->bytes_used += info->alloc.size; if (max_use < process->bytes_used) max_use = process->bytes_used; printf(" byte use = %ld, max_use = %d\n", process->bytes_used, max_use); g_hash_table_insert (block_table, info->alloc.new_ptr, block); } } while (process->command_queue && unqueue_command (process, info, &stack)) process_command (process, info, stack);}static gboolean input_func (GIOChannel *source, GIOCondition condition, gpointer data){ MIInfo info; guint count; MPProcess *input_process = data; MPProcess *process = NULL; g_io_channel_read (source, (char *)&info, sizeof(info), &count); if (count == 0) { g_io_channel_unref (input_process->input_channel); input_process->input_channel = NULL; mp_server_remove_process (input_process->server, input_process); process_set_status (input_process, MP_PROCESS_DEFUNCT); return FALSE; } else { StackElement *stack = NULL; if (info.operation == MI_MALLOC || info.operation == MI_REALLOC || info.operation == MI_FREE) { void **stack_buffer = NULL; StackStash *stash = get_stack_stash (input_process); stack_buffer = g_alloca (sizeof (void *) * info.alloc.stack_size); g_io_channel_read (source, (char *)stack_buffer, sizeof(void *) * info.alloc.stack_size, &count); stack = stack_stash_store (stash, stack_buffer, info.alloc.stack_size); } else if (info.operation == MI_EXIT) { process_set_status (input_process, MP_PROCESS_EXITING); if (input_process->clone_of) process_detach (input_process); } process = input_process; while (process->clone_of) process = process->clone_of; process_command (process, &info, stack);/* if (info.any.pid != input_process->pid) g_warning ("Ow! Ow! Ow: %d %d %d!", info.any.pid, input_process->pid, g_io_channel_unix_get_fd (input_process->input_channel)); */ } return TRUE;}voidprocess_stop_input (MPProcess *process){ g_return_if_fail (process != NULL); if (process->input_tag) { g_source_remove (process->input_tag); process->input_tag = 0; }}voidprocess_start_input (MPProcess *process){ g_return_if_fail (process != NULL); if (!process->input_tag && process->input_channel) process->input_tag = g_io_add_watch_full (process->input_channel, G_PRIORITY_LOW, G_IO_IN | G_IO_HUP, input_func, process, NULL);}char *process_find_exec (char **args){ int i; if (g_file_exists(args[0])) { if (!g_path_is_absolute (args[0])) return g_strconcat ("./", args[0], NULL); else return g_strdup (args[0]); } else { char **paths; char *path = NULL; char *pathenv = getenv ("PATH"); if (pathenv) { paths = g_strsplit (pathenv, ":", -1); for (i=0; paths[i]; i++) { path = g_concat_dir_and_file (paths[i], args[0]); if (g_file_exists (path)) break; else { g_free (path); path = NULL; } } g_strfreev (paths); } return path; }}char **process_parse_exec (const char *exec_string){ return g_strsplit (exec_string, " ", -1);}GTypemp_process_get_type (void){ static GType process_type = 0; if (!process_type) { static const GTypeInfo process_info = { sizeof (MPProcessClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) mp_process_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (MPProcess), 0, /* n_preallocs */ (GInstanceInitFunc) mp_process_init }; process_type = g_type_register_static (G_TYPE_OBJECT, "MPProcess", &process_info, 0); } return process_type;}static voidmp_process_class_init (MPProcessClass *class){ static gboolean initialized = FALSE; GObjectClass *o_class = G_OBJECT_CLASS (class); o_class->finalize = mp_process_finalize; if (!initialized) { process_signals[STATUS_CHANGED] = g_signal_new ("status_changed", MP_TYPE_PROCESS, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (MPProcessClass, status_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); process_signals[RESET] = g_signal_new ("reset", MP_TYPE_PROCESS, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (MPProcessClass, reset), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); initialized = TRUE; }}static voidmp_process_init (MPProcess *process){ process->status = MP_PROCESS_INIT; process->pid = 0; process->clone_of = NULL; process->bytes_used = 0; process->n_allocations = 0; process->block_table = NULL; process->stack_stash = NULL; process->program_name = NULL; process->input_channel = NULL; process->seqno = 0; process->command_queue = NULL; process->follow_fork = FALSE; process->follow_exec = FALSE; g_object_ref (G_OBJECT (process));}static void mp_process_finalize (GObject *object){ MPProcess *process = MP_PROCESS (object); process_reinit (process); g_free (process->program_name);}MPProcess *process_new (MPServer *server){ MPProcess *process; process = g_object_new (MP_TYPE_PROCESS, NULL); process->server = server; return process;}voidprocess_set_follow_fork (MPProcess *process, gboolean follow_fork){ process->follow_fork = follow_fork;}voidprocess_set_follow_exec (MPProcess *process, gboolean follow_exec){ process->follow_exec = follow_exec;}voidprocess_run (MPProcess *process, const char *path, char **args){ process->program_name = g_strdup (path); read_inode (path); process->pid = mp_server_instrument (process->server, path, args); mp_server_add_process (process->server, process); process_set_status (process, MP_PROCESS_STARTING); process_start_input (process);}GList *process_get_clones (MPProcess *process){ return mp_server_get_process_clones (process->server, process);}voidprocess_set_status (MPProcess *process, MPProcessStatus status){ if (process->status != status) { process->status = status; g_signal_emit_by_name (process, "status_changed", NULL); }}char *process_get_status_text (MPProcess *process){ char *status = ""; switch (process->status) { case MP_PROCESS_INIT: status = _("Initial"); break; case MP_PROCESS_STARTING: status = _("Starting"); break; case MP_PROCESS_RUNNING: status = _("Running"); break; case MP_PROCESS_EXITING: status = _("Exiting"); break; case MP_PROCESS_DEFUNCT: status = _("Defunct"); break; case MP_PROCESS_DETACHED: status = _("Defunct"); break; } return g_strdup (status);}char *process_get_cmdline (MPProcess *process){ char *fname; char *result; char *tmp = NULL; int n = 0; FILE *in = NULL; if (process->status == MP_PROCESS_DEFUNCT) return g_strdup (""); fname = g_strdup_printf ("/proc/%d/cmdline", process->pid); in = fopen (fname, "r"); if (!in) { g_warning ("Can't open %s\n", fname); return g_strdup (""); } g_free (fname); getline (&tmp, &n, in); result = g_strdup (tmp); free (tmp); fclose (in); return result;}voidprocess_detach (MPProcess *process){ if (process->status != MP_PROCESS_DEFUNCT) { int fd = g_io_channel_unix_get_fd (process->input_channel); if (process->status == MP_PROCESS_EXITING) { char response = 0; write (fd, &response, 1); } else { g_io_channel_close (process->input_channel); process_set_status (process, MP_PROCESS_DETACHED); } }}voidprocess_kill (MPProcess *process){ if (process->status == MP_PROCESS_EXITING) { process_detach (process); } else if (process->status != MP_PROCESS_DEFUNCT && process->status != MP_PROCESS_INIT) { kill (process->pid, SIGTERM); }}typedef struct { MPProcessBlockForeachFunc foreach_func; gpointer data;} BlockForeachInfo;static voidblock_table_foreach_func (gpointer key, gpointer value, gpointer data){ BlockForeachInfo *info = data; info->foreach_func (value, info->data);}voidprocess_block_foreach (MPProcess *process, MPProcessBlockForeachFunc foreach_func, gpointer data){ GHashTable *block_table = get_block_table (process); BlockForeachInfo info; info.foreach_func = foreach_func; info.data = data; g_hash_table_foreach (block_table, block_table_foreach_func, &info);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -