[Bug ipa/89893] Segmentation fault always occurs when node app is generated by gcc-8-branch@268745
marxin at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Tue Apr 2 07:28:00 GMT 2019
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89893
Martin Liška <marxin at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|ASSIGNED |RESOLVED
Resolution|--- |INVALID
--- Comment #8 from Martin Liška <marxin at gcc dot gnu.org> ---
Ok, so I did a deeper analysis and it looks there's a violation of aliasing:
bool PerIsolatePlatformData::FlushForegroundTasksInternal() {
bool did_work = false;
while (std::unique_ptr<DelayedTask> delayed =
foreground_delayed_tasks_.Pop()) {
did_work = true;
uint64_t delay_millis =
static_cast<uint64_t>(delayed->timeout + 0.5) * 1000;
delayed->timer.data = static_cast<void*>(delayed.get());
uv_timer_init(loop_, &delayed->timer);
// Timers may not guarantee queue ordering of events with the same delay if
// the delay is non-zero. This should not be a problem in practice.
uv_timer_start(&delayed->timer, RunForegroundTask, delay_millis, 0);
uv_unref(reinterpret_cast<uv_handle_t*>(&delayed->timer)); <---- HERE
scheduled_delayed_tasks_.emplace_back(delayed.release(),
[](DelayedTask* delayed) {
uv_close(reinterpret_cast<uv_handle_t*>(&delayed->timer), <---- HERE
[](uv_handle_t* handle) {
delete static_cast<DelayedTask*>(handle->data);
});
});
}
// Move all foreground tasks into a separate queue and flush that queue.
// This way tasks that are posted while flushing the queue will be run on the
// next call of FlushForegroundTasksInternal.
std::queue<std::unique_ptr<Task>> tasks = foreground_tasks_.PopAll();
while (!tasks.empty()) {
std::unique_ptr<Task> task = std::move(tasks.front());
tasks.pop();
did_work = true;
RunForegroundTask(std::move(task));
}
return did_work;
}
Taking look at struct definition I see:
struct uv_handle_s {
void* data; uv_loop_t* loop; uv_handle_type type; uv_close_cb close_cb; void*
handle_queue[2]; union { int fd; void* reserved[4]; } u; uv_handle_t*
next_closing; unsigned int flags;
};
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_timer_s uv_timer_t;
struct uv_timer_s {
void* data; uv_loop_t* loop; uv_handle_type type; uv_close_cb close_cb; void*
handle_queue[2]; union { int fd; void* reserved[4]; } u; uv_handle_t*
next_closing; unsigned int flags;
uv_timer_cb timer_cb; void* heap_node[3]; uint64_t timeout; uint64_t repeat;
uint64_t start_id;
};
When I use -fno-strict-aliasing, or when I mark uv_unref, then it's fine.
Similarly with -O2, the inling of uv_unref does not happen.
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 717c2e5..6bb3985 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -283,7 +283,7 @@ UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
UV_EXTERN void uv_stop(uv_loop_t*);
UV_EXTERN void uv_ref(uv_handle_t*);
-UV_EXTERN void uv_unref(uv_handle_t*);
+UV_EXTERN void __attribute__((noipa)) uv_unref(uv_handle_t*);
UV_EXTERN int uv_has_ref(const uv_handle_t*);
UV_EXTERN void uv_update_time(uv_loop_t*);
I'm going to create an upstream issue for it.
More information about the Gcc-bugs
mailing list