int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * attr) { PThreadCond * p = (PThreadCond *)loc_alloc_zero(sizeof(PThreadCond)); if (attr != NULL) { PThreadCondAttr * a = (PThreadCondAttr *)*attr; p->clock_id = a->clock_id; } else { p->clock_id = CLOCK_REALTIME; } p->waiters_count = 0; p->was_broadcast = 0; p->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); if (p->sema == NULL) return set_win32_errno(GetLastError()); InitializeCriticalSection(&p->waiters_count_lock); p->waiters_done = CreateEvent(NULL, FALSE, FALSE, NULL); if (p->waiters_done == NULL) return set_win32_errno(GetLastError()); *cond = (pthread_cond_t)p; return 0; }
static int get_sym_info(const Symbol * sym, DWORD index, SYMBOL_INFO ** res) { static ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * info = (SYMBOL_INFO *)buffer; HANDLE process = get_context_handle(sym->ctx->parent == NULL ? sym->ctx : sym->ctx->parent); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (!SymFromIndex(process, sym->module, index, info)) { set_win32_errno(GetLastError()); return -1; } *res = info; return 0; }
int pthread_cond_signal(pthread_cond_t * cond) { int have_waiters = 0; PThreadCond * p = (PThreadCond *)*cond; EnterCriticalSection(&p->waiters_count_lock); have_waiters = p->waiters_count > 0; LeaveCriticalSection(&p->waiters_count_lock); /* If there aren't any waiters, then this is a no-op. */ if (have_waiters) { if (!ReleaseSemaphore(p->sema, 1, 0)) return set_win32_errno(GetLastError()); } return 0; }
int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_back, void * args) { ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * symbol = (SYMBOL_INFO *)buffer; IMAGEHLP_STACK_FRAME stack_frame; EnumerateSymbolsContext enum_context; HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = MAX_SYM_NAME; if (frame == STACK_TOP_FRAME) frame = get_top_frame(ctx); if (frame == STACK_TOP_FRAME) return -1; if (get_stack_frame(ctx, frame, 0, &stack_frame) < 0) return -1; if (!SymSetContext(process, &stack_frame, NULL)) { DWORD err = GetLastError(); if (err == ERROR_SUCCESS) { /* Don't know why Windows does that */ } else { set_win32_errno(err); return -1; } } enum_context.ctx = ctx; enum_context.frame = frame; enum_context.call_back = call_back; enum_context.args = args; if (!SymEnumSymbols(process, 0, NULL, enumerate_symbols_proc, &enum_context)) { set_win32_errno(GetLastError()); return -1; } return 0; }
static int find_pe_symbol_by_addr(Context * ctx, int frame, ContextAddress addr, Symbol * sym) { HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * info = (SYMBOL_INFO *)buffer; IMAGEHLP_STACK_FRAME stack_frame; DWORD err; if (set_pe_context(ctx, frame, 0, process, &stack_frame) < 0) return -1; memset(info, 0, sizeof(SYMBOL_INFO)); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (SymFromAddr(process, addr, NULL, info)) { syminfo2symbol(ctx, frame, info, sym); return 0; } set_win32_errno(err = GetLastError()); if (err == 0 || err == ERROR_MOD_NOT_FOUND || err == ERROR_INVALID_ADDRESS) { errno = ERR_SYM_NOT_FOUND; } return -1; }
static int find_pe_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol * sym) { HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * info = (SYMBOL_INFO *)buffer; IMAGEHLP_STACK_FRAME stack_frame; DWORD err; if (set_pe_context(ctx, frame, ip, process, &stack_frame) < 0) return -1; memset(info, 0, sizeof(SYMBOL_INFO)); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (find_cache_symbol(ctx, frame, stack_frame.InstructionOffset, name, sym)) return errno ? -1 : 0; /* TODO: SymFromName() searches only main executable, need to search DLLs too */ if (SymFromName(process, name, info) && info->Tag != SymTagPublicSymbol) { syminfo2symbol(ctx, frame, info, sym); add_cache_symbol(ctx, stack_frame.InstructionOffset, name, sym, 0); return 0; } if (stack_frame.InstructionOffset != 0) { DWORD64 module = SymGetModuleBase64(process, stack_frame.InstructionOffset); if (module != 0 && SymGetTypeFromName(process, module, name, info)) { syminfo2symbol(ctx, frame, info, sym); add_cache_symbol(ctx, stack_frame.InstructionOffset, name, sym, 0); return 0; } } set_win32_errno(err = GetLastError()); if (err == 0 || err == ERROR_MOD_NOT_FOUND) { add_cache_symbol(ctx, stack_frame.InstructionOffset, name, NULL, ERR_SYM_NOT_FOUND); errno = ERR_SYM_NOT_FOUND; } return -1; }
int run_test_process(ContextAttachCallBack * done, void * data) { #if defined(_WIN32) char fnm[FILE_PATH_SIZE]; char cmd[FILE_PATH_SIZE]; int res = 0; STARTUPINFO si; PROCESS_INFORMATION prs; ContextAttachArgs * args; memset(&si, 0, sizeof(si)); memset(&prs, 0, sizeof(prs)); memset(fnm, 0, sizeof(fnm)); if (GetModuleFileName(NULL, fnm, sizeof(fnm)) == 0) { set_win32_errno(GetLastError()); return -1; } si.cb = sizeof(si); strcpy(cmd, "agent.exe -t"); if (CreateProcess(fnm, cmd, NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &prs) == 0) { set_win32_errno(GetLastError()); return -1; } args = (ContextAttachArgs *)loc_alloc(sizeof(ContextAttachArgs)); args->done = done; args->data = data; args->thread = prs.hThread; args->process = prs.hProcess; res = context_attach(prs.dwProcessId, done_context_attach, args, 0); if (res != 0) loc_free(args); return res; #elif defined(_WRS_KERNEL) int tid = taskCreate("tTcf", 100, 0, 0x4000, (FUNCPTR)test_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (tid == 0) return -1; taskStop(tid); taskActivate(tid); assert(taskIsStopped(tid)); return context_attach(tid, done, data, 0); #else int pid = fork(); if (pid < 0) return -1; if (pid == 0) { int fd = sysconf(_SC_OPEN_MAX); while (fd > 3) close(--fd); if (context_attach_self() < 0) exit(1); #if defined(__linux__) { char buf[32]; char * fnm = NULL; snprintf(buf, sizeof(buf), "/proc/%d/exe", getpid()); fnm = canonicalize_file_name(buf); if (fnm != NULL) execl(fnm, fnm, "-t", (char *)NULL); exit(1); } #else { if (tkill(getpid(), SIGSTOP) < 0) exit(1); test_proc(); exit(0); } #endif } return context_attach(pid, done, data, CONTEXT_ATTACH_SELF); #endif }
int get_symbol_name(const Symbol * sym, char ** name) { WCHAR * ptr = NULL; assert(sym->magic == SYMBOL_MAGIC); if (sym->base) { *name = NULL; return 0; } if (sym->info) { *name = sym->info->name; return 0; } *name = NULL; if (get_type_info(sym, TI_GET_SYMNAME, &ptr) < 0) ptr = NULL; if (ptr != NULL && wcscmp(ptr, L"<unnamed-tag>") == 0) ptr = NULL; if (ptr != NULL) { int len = 0; int err = 0; if (tmp_buf == NULL) { tmp_buf_size = 256; tmp_buf = (char *)loc_alloc(tmp_buf_size); } for (;;) { len = WideCharToMultiByte(CP_UTF8, 0, ptr, -1, tmp_buf, tmp_buf_size - 1, NULL, NULL); if (len != 0) break; err = GetLastError(); if (err != ERROR_INSUFFICIENT_BUFFER) { set_win32_errno(err); return -1; } tmp_buf_size *= 2; tmp_buf = (char *)loc_realloc(tmp_buf, tmp_buf_size); } HeapFree(GetProcessHeap(), 0, ptr); tmp_buf[len] = 0; *name = tmp_buf; } else { DWORD tag = 0; Symbol type = *sym; if (get_type_tag(&type, &tag)) return -1; if (tag == SymTagBaseType) { ContextAddress size = 0; int type_class = 0; unsigned char sign = 0; unsigned char real = 0; const TypeInfo * p = basic_type_info; if (get_symbol_size(&type, &size)) return -1; if (get_symbol_type_class(&type, &type_class)) return -1; if (type_class == TYPE_CLASS_INTEGER) sign = 1; else if (type_class == TYPE_CLASS_REAL) real = sign = 1; while (p->name != NULL) { if (p->size == size && p->sign == sign && p->real == real) { *name = p->name; break; } p++; } } } return 0; }
int pthread_mutex_unlock(pthread_mutex_t * mutex) { assert(mutex != NULL); assert(*mutex != NULL); if (!ReleaseMutex(*mutex)) return set_win32_errno(GetLastError()); return 0; }
int pthread_mutex_destroy(pthread_mutex_t * mutex) { assert(mutex != NULL); assert(*mutex != NULL); if (!CloseHandle(*mutex)) return set_win32_errno(GetLastError()); return 0; }
int pthread_mutex_lock(pthread_mutex_t * mutex) { assert(mutex != NULL); assert(*mutex != NULL); if (WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED) return set_win32_errno(GetLastError()); return 0; }
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) { assert(attr == NULL); *mutex = (pthread_mutex_t)CreateMutex(NULL, FALSE, NULL); if (*mutex == NULL) return set_win32_errno(GetLastError()); return 0; }
static void * worker_thread_handler(void * x) { WorkerThread * wt = (WorkerThread *)x; for (;;) { AsyncReqInfo * req = wt->req; assert(req != NULL); req->error = 0; switch(req->type) { case AsyncReqTimer: #if defined(_WIN32) && !defined(__CYGWIN__) Sleep(EVENTS_TIMER_RESOLUTION); events_timer_ms = GetTickCount(); #else { struct timespec timenow; usleep(EVENTS_TIMER_RESOLUTION * 1000); if (clock_gettime(CLOCK_REALTIME, &timenow) == 0) { events_timer_ms = (uint32_t)(timenow.tv_nsec / 1000000 + timenow.tv_sec * 1000); } } #endif break; case AsyncReqRead: /* File read */ req->u.fio.rval = read(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqWrite: /* File write */ req->u.fio.rval = write(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekRead: /* File read at offset */ req->u.fio.rval = pread(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSeekWrite: /* File write at offset */ req->u.fio.rval = pwrite(req->u.fio.fd, req->u.fio.bufp, req->u.fio.bufsz, (off_t)req->u.fio.offset); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecv: /* Socket recv */ req->u.sio.rval = recv(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqSend: /* Socket send */ req->u.sio.rval = send(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqRecvFrom: /* Socket recvfrom */ req->u.sio.rval = recvfrom(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, &req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqRecvFrom: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; case AsyncReqSendTo: /* Socket sendto */ req->u.sio.rval = sendto(req->u.sio.sock, req->u.sio.bufp, req->u.sio.bufsz, req->u.sio.flags, req->u.sio.addr, req->u.sio.addrlen); if (req->u.sio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqAccept: /* Accept socket connections */ req->u.acc.rval = accept(req->u.acc.sock, req->u.acc.addr, req->u.acc.addr ? &req->u.acc.addrlen : NULL); if (req->u.acc.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqAccept: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; case AsyncReqConnect: /* Connect to socket */ req->u.con.rval = connect(req->u.con.sock, req->u.con.addr, req->u.con.addrlen); if (req->u.con.rval == -1) { req->error = errno; trace(LOG_ASYNCREQ, "AsyncReqConnect: req %p, type %d, error %d", req, req->type, req->error); assert(req->error); } break; /* Platform dependant IO methods */ #if defined(_WIN32) || defined(__CYGWIN__) case AsyncReqConnectPipe: req->u.cnp.rval = ConnectNamedPipe(req->u.cnp.pipe, NULL); if (!req->u.cnp.rval) { req->error = set_win32_errno(GetLastError()); assert(req->error); } break; #elif defined(_WRS_KERNEL) #else case AsyncReqWaitpid: /* Wait for process change */ req->u.wpid.rval = waitpid(req->u.wpid.pid, &req->u.wpid.status, req->u.wpid.options); if (req->u.wpid.rval == -1) { req->error = errno; assert(req->error); } break; #endif case AsyncReqSelect: { struct timeval tv; tv.tv_sec = (long)req->u.select.timeout.tv_sec; tv.tv_usec = req->u.select.timeout.tv_nsec / 1000; req->u.select.rval = select(req->u.select.nfds, &req->u.select.readfds, &req->u.select.writefds, &req->u.select.errorfds, &tv); if (req->u.select.rval == -1) { req->error = errno; assert(req->error); } } break; case AsyncReqClose: req->u.fio.rval = close(req->u.fio.fd); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqCloseDir: req->u.dio.rval = closedir((DIR *)req->u.dio.dir); if (req->u.dio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqOpen: req->u.fio.rval = open(req->u.fio.file_name, req->u.fio.flags, req->u.fio.permission); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqOpenDir: req->u.dio.dir = opendir(req->u.dio.path); if (req->u.dio.dir == NULL) { req->error = errno; assert(req->error); } break; case AsyncReqFstat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = fstat(req->u.fio.fd, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error || !req->u.fio.file_name ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqStat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = stat(req->u.fio.file_name, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqLstat: memset(&req->u.fio.statbuf, 0, sizeof(req->u.fio.statbuf)); req->u.fio.rval = lstat(req->u.fio.file_name, &req->u.fio.statbuf); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } #if defined(_WIN32) || defined(__CYGWIN__) req->u.fio.win32_attrs = req->error ? INVALID_FILE_ATTRIBUTES : GetFileAttributes(req->u.fio.file_name); #endif break; case AsyncReqSetStat: { int err = 0; if (req->u.fio.set_stat_flags & AsyncReqSetSize) { if (truncate(req->u.fio.file_name, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno; } if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno; } #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL) # if defined(_WIN32) || defined(__CYGWIN__) if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) { if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0) err = set_win32_errno(GetLastError()); } # endif #else if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) { if (chown(req->u.fio.file_name, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno; } #endif if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) { struct utimbuf buf; buf.actime = req->u.fio.statbuf.st_atime; buf.modtime = req->u.fio.statbuf.st_mtime; if (utime(req->u.fio.file_name, &buf) < 0) err = errno; } req->error = err; } break; case AsyncReqFSetStat: { int err = 0; if (req->u.fio.set_stat_flags & AsyncReqSetSize) { if (ftruncate(req->u.fio.fd, (off_t)req->u.fio.statbuf.st_size) < 0) err = errno; } #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WRS_KERNEL) if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (chmod(req->u.fio.file_name, req->u.fio.statbuf.st_mode) < 0) err = errno; } # if defined(_WIN32) || defined(__CYGWIN__) if (req->u.fio.win32_attrs != INVALID_FILE_ATTRIBUTES) { if (SetFileAttributes(req->u.fio.file_name, req->u.fio.win32_attrs) == 0) err = set_win32_errno(GetLastError()); } # endif #else if (req->u.fio.set_stat_flags & AsyncReqSetUidGid) { if (fchown(req->u.fio.fd, req->u.fio.statbuf.st_uid, req->u.fio.statbuf.st_gid) < 0) err = errno; } if (req->u.fio.set_stat_flags & AsyncReqSetPermissions) { if (fchmod(req->u.fio.fd, req->u.fio.statbuf.st_mode) < 0) err = errno; } #endif if (req->u.fio.set_stat_flags & AsyncReqSetAcModTime) { struct utimbuf buf; buf.actime = req->u.fio.statbuf.st_atime; buf.modtime = req->u.fio.statbuf.st_mtime; #if defined(_WIN32) && !defined(__MINGW32__) if (futime(req->u.fio.fd, &buf) < 0) err = errno; #else if (utime(req->u.fio.file_name, &buf) < 0) err = errno; #endif } req->error = err; } break; case AsyncReqRemove: req->u.fio.rval = remove(req->u.fio.file_name); if (req->u.fio.rval == -1) { req->error = errno; assert(req->error); } break; case AsyncReqReadDir: { int cnt = 0; while (cnt < req->u.dio.max_files) { char path[FILE_PATH_SIZE]; struct DirFileNode * file = req->u.dio.files + cnt; struct dirent * e; struct stat st; errno = 0; e = readdir((DIR *)req->u.dio.dir); if (e == NULL) { req->error = errno; if (req->error == 0) req->u.dio.eof = 1; break; } if (strcmp(e->d_name, ".") == 0) continue; if (strcmp(e->d_name, "..") == 0) continue; file->path = loc_strdup(e->d_name); memset(&st, 0, sizeof(st)); snprintf(path, sizeof(path), "%s/%s", req->u.dio.path, e->d_name); if (stat(path, &st) == 0) { #if defined(_WIN32) || defined(__CYGWIN__) file->win32_attrs = GetFileAttributes(path); #endif file->statbuf = (struct stat *)loc_alloc(sizeof(struct stat)); memcpy(file->statbuf, &st, sizeof(struct stat)); } cnt++; } } break; case AsyncReqRoots: { struct stat st; struct RootDevNode * newDevNode = NULL; #if defined(_WIN32) || defined(__CYGWIN__) { struct RootDevNode * curDevNode = NULL; int disk = 0; DWORD disks = GetLogicalDrives(); for (disk = 0; disk <= 30; disk++) { if (disks & (1 << disk)) { char path[32]; newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; snprintf(path, sizeof(path), "%c:\\", 'A' + disk); newDevNode->devname = loc_strdup(path); if (disk >= 2) { ULARGE_INTEGER total_number_of_bytes; BOOL has_size = GetDiskFreeSpaceExA(path, NULL, &total_number_of_bytes, NULL); memset(&st, 0, sizeof(st)); #if defined(__CYGWIN__) snprintf(path, sizeof(path), "/cygdrive/%c", 'a' + disk); #endif if (has_size && stat(path, &st) == 0) { newDevNode->win32_attrs = GetFileAttributes(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } } } #elif defined(_WRS_KERNEL) { struct RootDevNode * curDevNode = NULL; extern DL_LIST iosDvList; DEV_HDR * dev; for (dev = (DEV_HDR *)DLL_FIRST(&iosDvList); dev != NULL; dev = (DEV_HDR *)DLL_NEXT(&dev->node)) { char path[FILE_PATH_SIZE]; if (strcmp(dev->name, "host:") == 0) { /* Windows host is special case */ int d; for (d = 'a'; d < 'z'; d++) { snprintf(path, sizeof(path), "%s%c:/", dev->name, d); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; newDevNode->devname = loc_strdup(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } snprintf(path, sizeof(path), "%s/", dev->name); if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); if (curDevNode == NULL) req->u.root.lst = newDevNode; else curDevNode->next = newDevNode; curDevNode = newDevNode; newDevNode->devname = loc_strdup(path); newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } } } #else req->u.root.lst = newDevNode = (struct RootDevNode *)loc_alloc_zero(sizeof(struct RootDevNode)); newDevNode->devname = loc_strdup("/"); if (stat("/", &st) == 0) { newDevNode->statbuf = (struct stat *)loc_alloc_zero(sizeof(struct stat)); memcpy(newDevNode->statbuf, &st, sizeof(struct stat)); } #endif } break; case AsyncReqUser: /* User defined request */ req->u.user.rval = req->u.user.func(req->u.user.data); if (req->u.user.rval == -1) { req->error = errno; assert(req->error); } break; default: req->error = ENOSYS; break; } if (req->type == AsyncReqTimer) { if (async_shutdown.state == SHUTDOWN_STATE_PENDING) break; continue; } trace(LOG_ASYNCREQ, "async_req_complete: req %p, type %d, error %d", req, req->type, req->error); check_error(pthread_mutex_lock(&wtlock)); /* Post event inside lock to make sure a new worker thread is not created unnecessarily */ post_event(req->done, req); wt->req = NULL; if (wtlist_size >= MAX_WORKER_THREADS || async_shutdown.state == SHUTDOWN_STATE_PENDING) { check_error(pthread_mutex_unlock(&wtlock)); break; } list_add_last(&wt->wtlink, &wtlist); wtlist_size++; for (;;) { check_error(pthread_cond_wait(&wt->cond, &wtlock)); if (wt->req != NULL) break; } check_error(pthread_mutex_unlock(&wtlock)); if (wt->req == &shutdown_req) break; } post_event(worker_thread_exit, wt); return NULL; }
static int start_process(Channel * c, char ** envp, char * dir, char * exe, char ** args, int attach, int * pid, int * selfattach, ChildProcess ** prs) { typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG Count; struct HANDLE_INFORMATION { USHORT ProcessId; USHORT CreatorBackTraceIndex; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } Handles[1]; } SYSTEM_HANDLE_INFORMATION; FARPROC QuerySystemInformationProc = GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtQuerySystemInformation"); DWORD size; NTSTATUS status; SYSTEM_HANDLE_INFORMATION * hi = NULL; int fpipes[3][2]; HANDLE hpipes[3][2]; char * cmd = NULL; int err = 0; int i; if (args != NULL) { int i = 0; int cmd_size = 0; int cmd_pos = 0; # define cmd_append(ch) { \ if (!cmd) { \ cmd_size = 0x1000; \ cmd = (char *)loc_alloc(cmd_size); \ } \ else if (cmd_pos >= cmd_size) { \ char * tmp = (char *)loc_alloc(cmd_size * 2); \ memcpy(tmp, cmd, cmd_pos); \ loc_free(cmd); \ cmd = tmp; \ cmd_size *= 2; \ }; \ cmd[cmd_pos++] = (ch); \ } while (args[i] != NULL) { char * p = args[i++]; if (cmd_pos > 0) cmd_append(' '); cmd_append('"'); while (*p) { if (*p == '"') cmd_append('\\'); cmd_append(*p); p++; } cmd_append('"'); } cmd_append(0); # undef cmd_append } size = sizeof(SYSTEM_HANDLE_INFORMATION) * 16; hi = loc_alloc(size); for (;;) { status = QuerySystemInformationProc(SystemHandleInformation, hi, size, &size); if (status != STATUS_INFO_LENGTH_MISMATCH) break; hi = loc_realloc(hi, size); } if (status == 0) { ULONG i; DWORD id = GetCurrentProcessId(); for (i = 0; i < hi->Count; i++) { if (hi->Handles[i].ProcessId != id) continue; SetHandleInformation((HANDLE)(int)hi->Handles[i].Handle, HANDLE_FLAG_INHERIT, FALSE); } } else { err = set_win32_errno(status); trace(LOG_ALWAYS, "Can't start process '%s': %s", exe, errno_to_str(err)); } loc_free(hi); memset(hpipes, 0, sizeof(hpipes)); for (i = 0; i < 3; i++) fpipes[i][0] = fpipes[i][1] = -1; if (!err) { #if defined(__CYGWIN__) for (i = 0; i < 3; i++) { if (pipe(fpipes[i]) < 0) { err = errno; break; } hpipes[i][0] = (HANDLE)get_osfhandle(fpipes[i][0]); hpipes[i][1] = (HANDLE)get_osfhandle(fpipes[i][1]); } #else for (i = 0; i < 3; i++) { if (!CreatePipe(&hpipes[i][0], &hpipes[i][1], NULL, PIPE_SIZE)) { err = set_win32_errno(GetLastError()); break; } fpipes[i][0] = _open_osfhandle((intptr_t)hpipes[i][0], O_TEXT); fpipes[i][1] = _open_osfhandle((intptr_t)hpipes[i][1], O_TEXT); } #endif } if (!err) { STARTUPINFO si; PROCESS_INFORMATION prs_info; SetHandleInformation(hpipes[0][0], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(hpipes[1][1], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(hpipes[2][1], HANDLE_FLAG_INHERIT, TRUE); memset(&si, 0, sizeof(si)); memset(&prs_info, 0, sizeof(prs_info)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = hpipes[0][0]; si.hStdOutput = hpipes[1][1]; si.hStdError = hpipes[2][1]; if (CreateProcess(exe, cmd, NULL, NULL, TRUE, (attach ? CREATE_SUSPENDED : 0), (envp ? envp[0] : NULL), (dir[0] ? dir : NULL), &si, &prs_info) == 0) { err = set_win32_errno(GetLastError()); } else { *pid = prs_info.dwProcessId; CloseHandle(prs_info.hThread); CloseHandle(prs_info.hProcess); } } close(fpipes[0][0]); close(fpipes[1][1]); close(fpipes[2][1]); if (!err) { *prs = loc_alloc_zero(sizeof(ChildProcess)); (*prs)->inp = fpipes[0][1]; (*prs)->out = fpipes[1][0]; (*prs)->err = fpipes[2][0]; (*prs)->pid = *pid; (*prs)->bcg = c->bcg; list_add_first(&(*prs)->link, &prs_list); } else { close(fpipes[0][1]); close(fpipes[1][0]); close(fpipes[2][0]); } loc_free(cmd); if (!err) return 0; trace(LOG_ALWAYS, "Can't start process '%s': %s", exe, errno_to_str(err)); errno = err; return -1; }
static void command_get_children(char * token, Channel * c) { char id[256]; int attached_only; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); attached_only = json_read_boolean(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); write_stringz(&c->out, "R"); write_stringz(&c->out, token); if (id[0] != 0) { write_errno(&c->out, 0); write_stringz(&c->out, "null"); } else { #if defined(WIN32) DWORD err = 0; HANDLE snapshot; PROCESSENTRY32 pe32; snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot == INVALID_HANDLE_VALUE) err = set_win32_errno(GetLastError()); memset(&pe32, 0, sizeof(pe32)); pe32.dwSize = sizeof(PROCESSENTRY32); if (!err && !Process32First(snapshot, &pe32)) { err = set_win32_errno(GetLastError()); CloseHandle(snapshot); } write_errno(&c->out, err); if (err) { write_stringz(&c->out, "null"); } else { int cnt = 0; write_stream(&c->out, '['); do { if (!attached_only || context_find_from_pid(pe32.th32ProcessID) != NULL) { if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, pid2id(pe32.th32ProcessID, 0)); cnt++; } } while (Process32Next(snapshot, &pe32)); write_stream(&c->out, ']'); write_stream(&c->out, 0); } if (snapshot != INVALID_HANDLE_VALUE) CloseHandle(snapshot); #elif defined(_WRS_KERNEL) int i = 0; int cnt = 0; int ids_cnt = 0; int ids_max = 500; int * ids = (int *)loc_alloc(ids_max * sizeof(int)); for (;;) { ids_cnt = taskIdListGet(ids, ids_max); if (ids_cnt < ids_max) break; loc_free(ids); ids_max *= 2; ids = (int *)loc_alloc(ids_max * sizeof(int)); } write_errno(&c->out, 0); write_stream(&c->out, '['); for (i = 0; i < ids_cnt; i++) { if (!attached_only || context_find_from_pid(ids[i]) != NULL) { if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, pid2id(ids[i], 0)); cnt++; } } write_stream(&c->out, ']'); write_stream(&c->out, 0); #elif defined(__APPLE__) #else DIR * proc = opendir("/proc"); if (proc == NULL) { write_errno(&c->out, errno); write_stringz(&c->out, "null"); } else { int cnt = 0; write_errno(&c->out, 0); write_stream(&c->out, '['); for (;;) { struct dirent * ent = readdir(proc); if (ent == NULL) break; if (ent->d_name[0] >= '1' && ent->d_name[0] <= '9') { pid_t pid = atol(ent->d_name); if (!attached_only || context_find_from_pid(pid) != NULL) { if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, pid2id(pid, 0)); cnt++; } } } write_stream(&c->out, ']'); write_stream(&c->out, 0); closedir(proc); } #endif } write_stream(&c->out, MARKER_EOM); }