ph_result_t ph_hook_unregister_cstr(const char *name, ph_hook_func func, void *closure) { ph_hook_point_t *hp = ph_hook_point_get_cstr(name, true); if (!hp) { return PH_ERR; } return do_unregister(hp, func, closure); }
void ph_logv(uint8_t level, const char *fmt, va_list ap) { struct timeval now = ph_time_now(); ph_thread_t *me; int len; va_list copy; char *buf; PH_STRING_DECLARE_STACK(mystr, 1024); void *args[] = { &level, &mystr }; static ph_hook_point_t *hook = NULL; char tname[32]; if (level > log_level) { return; } len = strlen(fmt); if (len == 0) { return; } me = ph_thread_self(); get_tname(me, tname, sizeof(tname)); va_copy(copy, ap); ph_string_printf(&mystr, "%" PRIi64 ".%03d %s: %s `Pv%s%p%s", (int64_t)now.tv_sec, (int)(now.tv_usec / 1000), log_labels[level], tname, fmt, ph_vaptr(copy), fmt[len-1] == '\n' ? "" : "\n"); va_end(copy); if (ph_unlikely(hook == NULL)) { hook = ph_hook_point_get_cstr(PH_LOG_HOOK_NAME, true); } ph_hook_invoke_inner(hook, sizeof(args)/sizeof(args[0]), args); if (disable_stderr) { return; } pthread_mutex_lock(&log_lock); buf = mystr.buf; len = mystr.len; while (len) { int x = write(STDERR_FILENO, buf, len); if (x <= 0) { break; } buf += x; len -= x; } pthread_mutex_unlock(&log_lock); }