| 503 | } |
| 504 | |
| 505 | void LogFinalize() |
| 506 | { |
| 507 | if (!IsServerInitialized()) |
| 508 | { |
| 509 | CloseLogFile(); |
| 510 | return; |
| 511 | } |
| 512 | |
| 513 | dmLogServer* self = g_dmLogServer; |
| 514 | |
| 515 | LogMessage msg; |
| 516 | msg.m_Type = LogMessage::SHUTDOWN; |
| 517 | dmMessage::URL receiver; |
| 518 | receiver.m_Socket = self->m_MessageSocket; |
| 519 | receiver.m_Path = 0; |
| 520 | receiver.m_Fragment = 0; |
| 521 | dmMessage::Post(0, &receiver, 0, 0, 0, &msg, sizeof(msg), 0); |
| 522 | |
| 523 | // Make sure we have control of the context |
| 524 | dmAtomicStore32(&g_LogServerInitialized, 0); |
| 525 | |
| 526 | if (self->m_Thread) |
| 527 | dmThread::Join(self->m_Thread); |
| 528 | |
| 529 | { |
| 530 | DM_SPINLOCK_SCOPED_LOCK(g_LogServerLock); |
| 531 | |
| 532 | uint32_t n = self->m_Connections.Size(); |
| 533 | for (uint32_t i = 0; i < n; ++i) |
| 534 | { |
| 535 | dmLogConnection* c = &self->m_Connections[i]; |
| 536 | dmSocket::Shutdown(c->m_Socket, dmSocket::SHUTDOWNTYPE_READWRITE); |
| 537 | dmSocket::Delete(c->m_Socket); |
| 538 | c->m_Socket = dmSocket::INVALID_SOCKET_HANDLE; |
| 539 | } |
| 540 | |
| 541 | if (self->m_ServerSocket != dmSocket::INVALID_SOCKET_HANDLE) |
| 542 | { |
| 543 | dmSocket::Delete(self->m_ServerSocket); |
| 544 | self->m_ServerSocket = dmSocket::INVALID_SOCKET_HANDLE; |
| 545 | } |
| 546 | |
| 547 | if (self->m_MessageSocket != 0) |
| 548 | { |
| 549 | dmMessage::DeleteSocket(self->m_MessageSocket); |
| 550 | } |
| 551 | |
| 552 | delete self; |
| 553 | g_dmLogServer = 0; |
| 554 | CloseLogFile(); |
| 555 | } |
| 556 | |
| 557 | dmSpinlock::Destroy(&g_ListenerLock); |
| 558 | dmSpinlock::Destroy(&g_LogServerLock); |
| 559 | } |
| 560 | |
| 561 | uint16_t GetPort() |
| 562 | { |