123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- #include "precompile.h"
- #include "process_monitor.h"
- #include "list.h"
- #include "spinlock.h"
- #include "dbgutil.h"
- #include <winpr/synch.h>
- #include <winpr/thread.h>
- #define CMD_REMOVE 0
- #define CMD_ADD 1
- #define CMD_EXIT 2
- #define EVT_IDX 0
- #define INIT_CNT 1
- typedef struct cmd_entry_t
- {
- struct list_head entry;
- int cmd;
- HANDLE hproc;
- HANDLE wait_evt;
- int result;
- }cmd_entry_t;
- typedef struct monitor_t
- {
- struct list_head entry;
- HANDLE thread;
- /*[evt, process_handle1, process_handle2,..., process_handleN] */
- HANDLE arr_handle[MAXIMUM_WAIT_OBJECTS];
- int arr_cnt;
- struct list_head cmd_list;
- process_monitor_t *parent;
- }monitor_t;
- struct process_monitor_t
- {
- struct list_head full_monitor_list;
- struct list_head avail_monitor_list;
- CRITICAL_SECTION lock;
- process_monitor_on_detect_process_end cb;
- void *user_data;
- };
- static void process_monitor_lock(process_monitor_t *pm)
- {
- EnterCriticalSection(&pm->lock);
- }
- static void process_monitor_unlock(process_monitor_t *pm)
- {
- LeaveCriticalSection(&pm->lock);
- }
- static unsigned int __stdcall monitor_thread_proc(void *arg)
- {
- monitor_t *monitor = (monitor_t*)arg;
- for (;;) {
- DWORD dwRet = WaitForMultipleObjects(monitor->arr_cnt, monitor->arr_handle, FALSE, INFINITE);
- if (dwRet == WAIT_OBJECT_0+EVT_IDX)
- {
- cmd_entry_t *cmd = list_first_entry(&monitor->cmd_list, cmd_entry_t, entry);
- list_del(&cmd->entry);
- if (cmd->cmd == CMD_ADD)
- {
- monitor->arr_handle[monitor->arr_cnt++] = cmd->hproc;
- cmd->result = 0;
- if (cmd->wait_evt)
- SetEvent(cmd->wait_evt);
- }
- else if (cmd->cmd == CMD_REMOVE)
- {
- int i;
- cmd->result = -1;
- for (i = 0; i < monitor->arr_cnt; ++i)
- {
- if (monitor->arr_handle[i] == cmd->hproc) {
- if (i != monitor->arr_cnt-1) {
- monitor->arr_handle[i] = monitor->arr_handle[monitor->arr_cnt-1];
- }
- monitor->arr_cnt--;
- cmd->result = 0;
- break;
- }
- }
- if (cmd->wait_evt)
- SetEvent(cmd->wait_evt);
- }
- else if (cmd->cmd == CMD_EXIT)
- {
- cmd->result = 0;
- if (cmd->wait_evt)
- SetEvent(cmd->wait_evt);
- break;
- }
- else
- {
- cmd->result = -1;
- if (cmd->wait_evt)
- SetEvent(cmd->wait_evt);
- }
- }
- else if (dwRet >= WAIT_OBJECT_0 && dwRet < WAIT_OBJECT_0 + monitor->arr_cnt)
- {
- int idx = dwRet - WAIT_OBJECT_0;
- HANDLE hProc = monitor->arr_handle[idx];
- if ((*monitor->parent->cb)(monitor->parent, hProc, monitor->parent->user_data)) {
- if (monitor->arr_handle[idx] == hProc) {
- if (idx != monitor->arr_cnt-1)
- monitor->arr_handle[idx] = monitor->arr_handle[monitor->arr_cnt-1];
- monitor->arr_cnt --;
- }
- else {
- TOOLKIT_ASSERT(0);
- }
- }
- }
- else
- {
- // TOOLKIT_ASSERT(0);
- // return -1;
- }
- }
- return 0;
- }
- TOOLKIT_API int process_monitor_add(process_monitor_t *monitor, tk_process_t* process)
- {
- cmd_entry_t ce;
- monitor_t *m = NULL;
- TOOLKIT_ASSERT(monitor);
- TOOLKIT_ASSERT(process != NULL);
- ce.wait_evt = CreateEventA(NULL, FALSE, FALSE, NULL);
- if (!ce.wait_evt)
- return -1;
- ce.cmd = CMD_ADD;
- ce.hproc = process->handle;
- process_monitor_lock(monitor);
- if (list_empty(&monitor->avail_monitor_list)) {
- m = MALLOC_T(monitor_t);
- if(m == NULL) {
- CloseHandle(ce.wait_evt);
- return -1;
- }
- m->arr_cnt = INIT_CNT;
- /*
- *The state of a semaphore is signaled when its count is greater than zero
- *the count is increased by a specified amount by calling ReleaseSemaphore.
- */
- m->arr_handle[EVT_IDX] = CreateSemaphoreA(NULL, 0, 0x7fffffff, NULL);
- if (!m->arr_handle[EVT_IDX]) {
- free(m);
- CloseHandle(ce.wait_evt);
- process_monitor_unlock(monitor);
- return -1;
- }
- m->parent = monitor;
- m->thread = (HANDLE)_beginthreadex(NULL, 0, &monitor_thread_proc, m, 0, NULL);
- if (!m->thread) {
- CloseHandle(m->arr_handle[EVT_IDX]);
- CloseHandle(ce.wait_evt);
- free(m);
- process_monitor_unlock(monitor);
- return -1;
- }
- INIT_LIST_HEAD(&m->cmd_list);
- /*only one elem at current time*/
- list_add_tail(&m->entry, &monitor->avail_monitor_list);
- } else {
- /*get the existed elem*/
- m = list_first_entry(&monitor->avail_monitor_list, monitor_t, entry);
- }
- list_add_tail(&ce.entry, &m->cmd_list);
- ReleaseSemaphore(m->arr_handle[EVT_IDX], 1, NULL);
- /*wait CMD_ADD cmd result.*/
- WaitForSingleObject(ce.wait_evt, INFINITE);
- if (m->arr_cnt == MAXIMUM_WAIT_OBJECTS) {
- list_del(&m->entry);
- list_add_tail(&m->entry, &monitor->full_monitor_list);
- }
- process_monitor_unlock(monitor);
- CloseHandle(ce.wait_evt);
- return ce.result;
- }
- TOOLKIT_API int process_monitor_remove(process_monitor_t *monitor, tk_process_t* process)
- {
- cmd_entry_t ce;
- TOOLKIT_ASSERT(monitor);
- TOOLKIT_ASSERT(process);
- ce.wait_evt = CreateEventA(NULL, FALSE, FALSE, NULL);
- if (!ce.wait_evt)
- return -1;
- ce.cmd = CMD_REMOVE;
- ce.hproc = process->handle;
- ce.result = -1;
- process_monitor_lock(monitor);
- {
- monitor_t *pos;
- list_for_each_entry(pos, &monitor->full_monitor_list, monitor_t, entry) {
- list_add_tail(&ce.entry, &pos->cmd_list);
- ReleaseSemaphore(pos->arr_handle[EVT_IDX], 1, NULL);
- WaitForSingleObject(ce.wait_evt, INFINITE);
- if (ce.result == 0) {
- list_del(&pos->entry);
- list_add_tail(&pos->entry, &monitor->avail_monitor_list);
- break;
- }
- }
- if (ce.result == -1) {
- list_for_each_entry(pos, &monitor->avail_monitor_list, monitor_t, entry) {
- list_add_tail(&ce.entry, &pos->cmd_list);
- ReleaseSemaphore(pos->arr_handle[EVT_IDX], 1, NULL);
- WaitForSingleObject(ce.wait_evt, INFINITE);
- if (ce.result == 0) {
- break;
- }
- }
- }
- }
- process_monitor_unlock(monitor);
- CloseHandle(ce.wait_evt);
- return ce.result;
- }
- TOOLKIT_API int process_monitor_create(process_monitor_t **p_monitor)
- {
- process_monitor_t *pm = MALLOC_T(process_monitor_t);
- INIT_LIST_HEAD(&pm->full_monitor_list);
- INIT_LIST_HEAD(&pm->avail_monitor_list);
- InitializeCriticalSection(&pm->lock);
- pm->cb = NULL;
- *p_monitor = pm;
- return 0;
- }
- TOOLKIT_API int process_monitor_destroy(process_monitor_t *monitor)
- {
- int i;
- struct list_head *lists[] = {&monitor->avail_monitor_list, &monitor->full_monitor_list};
- for (i = 0; i < array_size(lists); ++i) {
- monitor_t *pos, *n;
- list_for_each_entry_safe(pos, n, lists[i], monitor_t, entry) {
- cmd_entry_t ce;
- ce.cmd = CMD_EXIT;
- ce.wait_evt = NULL;
- list_add_tail(&ce.entry, &pos->cmd_list);
- ReleaseSemaphore(pos->arr_handle[EVT_IDX], 1, NULL);
- WaitForSingleObject(pos->thread, INFINITE);
- list_del(&pos->entry);
- CloseHandle(pos->thread);
- CloseHandle(pos->arr_handle[EVT_IDX]);
- free(pos);
- }
- }
- DeleteCriticalSection(&monitor->lock);
- free(monitor);
- return 0;
- }
- TOOLKIT_API int process_monitor_set_cb(process_monitor_t *monitor, process_monitor_on_detect_process_end cb, void *user_data)
- {
- monitor->cb = cb;
- monitor->user_data = user_data;
- return 0;
- }
- TOOLKIT_API int process_monitor_stop(process_monitor_t *monitor)
- {
- return 0;
- }
|