----------------threadpool.c-----------------
int uv_queue_work(uv_loop_t* loop,
uv_work_t* req,
uv_work_cb work_cb,
uv_after_work_cb after_work_cb) {
if (work_cb == NULL)
return UV_EINVAL;
uv__req_init(loop, req, UV_WORK);
req->loop = loop;
req->work_cb = work_cb;
req->after_work_cb = after_work_cb;
uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done);
return 0;
}
void uv__work_submit(uv_loop_t* loop,
struct uv__work* w,
void (_work)(struct uv__work_ w),
void (_done)(struct uv__work_ w, int status)) {
uv_once(&once, init_once);
w->loop = loop;
w->work = work;
w->done = done;
post(&w->wq);
}
static void post(QUEUE* q) {
uv_mutex_lock(&mutex);
QUEUE_INSERT_TAIL(&wq, q);
if (idle_threads > 0)
uv_cond_signal(&cond);
uv_mutex_unlock(&mutex);
}
SEE-,
uv__work_submit is thread safe, but uv__req_init not.
uv_queue_work can be invoked in other thread, how terrible it is!!
I mean uv_queue_work can not be invoked in other thread, how terrible it is!!
I am not sure why this would be terrible or a design bug. Also, this is probably out of scope for the Node.js issue tracker, as far as I can see this question concerns libuv in general.
agreed, please take it to https://github.com/libuv/libuv
I run node in cluster mode. All workers send infos to master. The master send infos to only one log process. In the log process, infos will be write to disk in other thread.
SEE-,
void RcibHelper::PrintLogs(const std::string & info, async_req * req){
if (fp_){
std::string content = info + "n";
fputs(content.c_str(), fp_);
}
//TODO use direct way
uv_queue_work(uv_default_loop(),
&req->req,
DoNopAsync,
(uv_after_work_cb)AfterAsync);
}
PrintLogs runs in a thread that created when the c++ module required. but uv_queue_work actually only run on the main thread. Really bad mood!!
My codes can be found by -> npm install rcib
I delete uv__req_register. if not ,error occurs
node: ../deps/uv/src/threadpool.c:252: uv__queue_done: Assertion `(((const QUEUE ) (&(req->loop)->active_reqs) == (const QUEUE *) ((QUEUE *) &(((&(req->loop)->active_reqs))[0]))) == 0)' failed.
change threadpool.c ....
static void uv__queue_done_self(struct uv__work* w, int err) {
uv_work_t* req;
req = container_of(w, uv_work_t, work_req);
if (req->after_work_cb == NULL)
return;
req->after_work_cb(req, err);
}
void uv__req_register_self(uv_loop_t* loop,
uv_req_t* req, uv_req_type type){
req->type = type;
}
void post_self(QUEUE* q) {
QUEUE_INSERT_TAIL(&wq, q);
if (idle_threads > 0)
uv_cond_signal(&cond);
}
void uv__work_submit_self(uv_loop_t* loop,
struct uv__work* w,
void (work)(struct uv__work w),
void (done)(struct uv__work w, int status)) {
w->loop = loop;
w->work = work;
w->done = done;
post_self(&w->wq);
}
int uv_queue_work(uv_loop_t* loop,
uv_work_t* req,
uv_work_cb work_cb,
uv_after_work_cb after_work_cb) {
if (work_cb == NULL)
return UV_EINVAL;
uv_once(&once, init_once);
uv_mutex_lock(&mutex);
uv__req_register_self(loop, (uv_req_t*)req, UV_WORK);
req->loop = loop;
req->work_cb = work_cb;
req->after_work_cb = after_work_cb;
uv__work_submit_self(loop, &req->work_req, uv__queue_work, uv__queue_done_self);
uv_mutex_unlock(&mutex);
return 0;
}
Most helpful comment
agreed, please take it to https://github.com/libuv/libuv