이 블로그 검색

2017년 12월 24일 일요일

oracle PCC-S-02322, found undefined identifier 에러 발생의 어이없는 이유

지금 하고있는 프로젝트에서 오라클을 사용하는 부분이 있어서, 그 옛날의 proc 를 사용해서 개발하는 부분이 있는데, 이런 오류가 발생했다.

PCC-S-02322, found undefined identifier

그런데 소스 변경은 하나도 하지 않고, 단지 서버 장비만 변경된 경우이다.
이것 저것 확인하여 알아낸 사실은, 소스 코드내에서의 문제가 아니고 oracle NLS_LANG 설정이 기존과 다르면 발생할수 있다.

이 설정이 기존에는 AMERICAN_AMRRICA.UTF8 인데 변경된 장비에서는 AMERICAN_ARERICA.KO16KSC5601 로 되어 있었다.
(그리고 pc 소스파일은 utf-8로 인코딩 된 상태)
이설정을 원래대로 하고 컴파일 하니 이상없게 된다.

그런데 왜 난데없이 undefined identifier 라는 에러가 튀어나오는지는 정말 어이없고 마음에 안든다.  

2017년 12월 3일 일요일

localtime_r 은 thread safe 하지 않다? deadlock발생 경우.

며칠 전 개발하면서 겪었던 상황인데,
fork 된 child process에서는 localtime_r 과 같은 시간관련 함수를 사용할때 유의해야 한다.

localtime 함수는 시간을 구하는 함수이다.
이 함수는 내부적으로 static 변수에 값을 저장하기 때문에 thread safe하지 않다.
그래서 멀티 쓰레드 환경에서는 localtime_r 을 사용하게 된다.
여기까지는 일반적으로 다들 알고 있는 내용일 것이다.
그런데 localtime_r 함수를 사용해도 문제가 되는 경우가 발생했다.
fork 함수와 multi thread 가 만나면 문제가 된다.
다음 코드처럼, run_child_process 라는 함수가 멀티쓰레드에서 호출되며,
함수 내부에서는 fork를 이용해서 자식 프로세스를 생성하고 있는 경우를 생각해보자.
만약 fork 된 자식 process에서 logging이 발생되는 경우, deadlock 이 발생할수도 있다
(logging 을 처리는 내부적으로 localtime_r 함수를 사용중이다).


void SomeUtilClass::run_child_process(const char* command)
{
    LOGD("run this command [%s]", command); //logging macro이다.내부적으로 localtime_r 을 호출한다.
    pid_t pid = fork(command);
    if(pid >0)
    {
        //parent
    }
    else if(pid == 0 )
    {
        //child
        LOGD("child started..."); //XXX fork 된 child에서 logging 호출!
        ....
    }
    .....
}


멀티쓰레드 문제가 대부분 그렇듯.. 항상 deadlock 이 발생하는게 아니고,
운이 나쁘면 종종 발생한다는것이 큰 문제다.

이 코드가 문제가 되는 이유는, localtime_r 호출 시 내부적으로 lock이 걸리는데 fork와 같이 사용되면서
lock 이 잠긴 상태에서 다시 lock을 잡게 되는 경우가 발생 가능하기 때문이다(즉 deadlock).

즉, 다음 순서가 재현되면 deadlock 이 발생한다.

1. 부모 프로세스가 멀티 쓰레드를 생성하고 각 쓰레드가 run_child_process 를 호출한다
2. 부모 프로세스가 logging을 호출하게 된다.
3. fork된 자식 프로세스도 logging 을 호출한다. 그런데 fork된 자식 프로세스는 부모의 lock도 상속받는다.
   (The entire virtual address space of the  parent  is replicated  in  the  child, 
    including  the  states  of  mutexes,  condition  variables,  and  other  pthreads objects;)

4. 이때 운나쁘게 부모가 잡은 lock이 풀리기 전(localtime_r 호출이 종료되기 전) 에
   자식이 다시 lock을 얻는 시도(localtime_r 호출)를 하게되면 deadlock에 빠진다.

fork 를 사용하는 경우에는,  부모 로부터 뭔가를 상속 받는다는 것을 유념하고, 조심해야겠다..

2017년 10월 21일 토요일

ubuntu server virtualbox remote ssh root login 설정

ubuntu 서버 virtualbox 원격 ssh 로그인 설정

1.root 계정 생성  : sudo passwd root 수행 후 su 수행.

2.ubuntu server 에 sshd 동작 확인 --> ps -ef | grep sshd
  설치 안된 경우엔 apt-get install openssh-server -y
 
3.ssh root login 설정 :  vi /etc/ssh/sshd_config , PermitRootLogin yes 변경.

4.virtualbox 의 네트워크 환경 어댑터 2 는 불필요, 기본 어댑터의 포트 포워딩에 추가.
   예를 들어, os x 터미널에서 ssh root@127.0.0.1 -p1234 처럼 접속하기 위해서는 다음처럼 설정한다.
   

5. ubuntu 재시동 후 ssh root@127.0.0.1 -p1234 로그인 확인



2017년 10월 8일 일요일

c++ thread pool


https://github.com/jeremyko/kothreadpool

간단한 worker thread pool 정도만 필요해서 하나 만들어 보았다.
사용법은 다음과 같다.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <string>
#include <atomic>
#include "KoThreadPool.hpp"

std::atomic<int> gSum1;
std::atomic<int> gSum2;


bool MyThreadWork()
{
    gSum1++;
    return true;
}


class MyClass
{
    public:
        MyClass()  {} ;
        ~MyClass() {} ;

        bool MyThreadWork()
        {
            gSum2++;

            return true;
        }

};


int main()
{
    KoThreadPool tpool;

    if( ! tpool.InitThreadPool() ) 
    {
        std::cerr << "Error : Init" << "\n";
        exit(1);
    }

    gSum1 = 0;
    gSum2 = 0;

    MyClass myclass;

    int i = 0;
    while(true)
    {
        if(i >= 10000)
        {
            break;
        }

        //class member
        std::function<void()> temp_func1 = std::bind( &MyClass::MyThreadWork, &myclass)  ;
        tpool.AssignTask(temp_func1 )  ;

        //free function
        std::function<void()> temp_func2 = std::bind( &MyThreadWork )  ;
        tpool.AssignTask(temp_func2 )  ;
        i++;
    }
    tpool.Terminate(); //graceful terminate : wait until all work done
    //tpool.Terminate(true); //terminate immediately
    
    std::cout << "gSum1 =" << gSum1 << "\n";
    std::cout << "gSum2 =" << gSum2 << "\n";
    
    

    return 0;
}

jeremykoui-MacBook-Pro:sample jeremyko$ ./simple_test
std::thread::hardware_concurrency() = 8
gSum1 =10000
gSum2 =10000

2017년 4월 26일 수요일

변기 디버깅 : 원피스 변기 앞쪽 물 안내려감

이글은 프로그래밍과 관련없음.
화장실 원피스 변기 수리(디버깅)하면서 알게된 내용을 기록 하고자 한다. ^^

먼저 간단한 결론:

다음 항목에 해당되는 경우 간단한 해결책이 존재한다
  • 변기 유형이 원피스 변기다.
  • 화장실 수압은 정상이다 (물이 졸졸 나오는 수준만 아니면 된다).
  • 화장실 변기 물이 천천히 차오른다
  • 물내릴때 변기 앞쪽 옆쪽으로 물이 안나온다
  • 그래서 비록 변은 내려가지만 앞쪽 휴지 한장조차 시원히 안내려간다.

2017년 2월 10일 금요일

close(0) 로 인한 stdin close : getline, getchars 동작 이상

왜 getline() 함수가 즉시 리턴되는가? 에 대한 삽질의 기억...


class SomeClass
{
    ...
    int nSockFd_  {0}; //초기화를 0 으로 한 경우.
    ...
};     

void SomeClass::SomeMethod1()
{
    .... 
    //코드 어딘가에서 다음을 호출했는데... 아직 nSockFd_ 가 할당안된 경우 
    close(nSockFd_); //--> close(0) --> stdin 을 닫아버림 - - ;;
    ... 
}

void SomeClass::SomeMethod2()
{ 
   ....  
   std::string line="";
    while(true)
    {  
        std::cin.clear();
        getline(std::cin, line); //여기서 문제 발생, 즉시 리턴됨
        std::cout << "msg:" << line << std::endl;
    }
}

2017년 2월 5일 일요일

Cumbuffer 를 이용한 예제 : ASockLib


https://github.com/jeremyko/ASockLib


CumBuffer 를 사용하는 예제 겸 TCP/UDP/Domain socket 네트워크 라이브러리를 작성해 보았다. 비록 허접하지만 cross platform 에서 동일한 interface 를 지원해보자는 생각이 있어서.... linux 에서는 epoll, os x 에서는 kqueue 를 사용해서 구현 되었다. cmake를 사용해서 cross platform compile 을 지원하게 해보았다. 클래스 상속과 포함(composition) 2가지 방식으로 사용 가능한다. 그리고 비동기 send 호출시 block 되는 경우에는 큐에 저장되었다가 전송 가능한 시점에 재개되는 방식으로 처리했다. 지금 수행중인 SI 과금 프로젝트에서 이걸 적용하면서 개발중이다.