manywaypark's Blog
개발, 검색, 함수

Function has no local return

함수형 언어/Elixir 2020. 2. 27. 20:22 by manywaypark

dialyzer(discrepancy analyzer)는 Erlang의 static analyzer(정적분석도구)이다. type safety가 확보되면 아주 많은 오류를 줄일 수 있다. 그런데 이 좋은 도구인 dialyzer를 사용하다보면 언듯 보기에 멀쩡한 부분에서 "function foo/2 has no local return" 이라는 경고를 만나게 된다.

일단 참고 아티클에서 발췌:

'Function Name/Arity has no local return' is the standard Dialyzer warning emitted whenever a function provably doesn't return anything (other than perhaps raising an exception) because one of the function it calls happens to trip Dialyzer's type error detector or raises an exception itself. When such a thing happens, the set of possible types of values the function could return is empty; it doesn't actually return. This error propagates to the function that called it, giving us the 'no local return' error.

대충 요약하자면 return이 없거나 영원이 return되지 않을 것(crash 등)으로 추측되는 경우 dialyzer에서 이 경고가 나온다는 말인데...

내 경험상 해결 방법은 다음 방법들 중에 하나를 쓰면 된다. 

  1. dialyer에게 type inference hint를 준다. 즉, @spec을 제대로 써주면 해결됨 (dialyer는 좁은 범위를 제시하면 훨씬 똑똑하게 동작함)
  2. error, exception, raise 등이 발생하는 경우(1차적으로 눈에 보이지 않더라도 call stack을 따라 전파됨) return type에 명시적으로 return이 없을 수 있다고 명시한다.
    - Erlang은 no_return()
    - Elixir는 RuntimeError를 try rescue/catch 등의 방법으로 처리

 

ref: https://learnyousomeerlang.com/dialyzer#typing-about-types-of-types

 

Type Specifications and Erlang | Learn You Some Erlang for Great Good!

Hey there, it appears your Javascript is disabled. That's fine, the site works without it. However, you might prefer reading it with syntax highlighting, which requires Javascript! Type Specifications and Erlang Back in Types (or lack thereof), I introduce

learnyousomeerlang.com

happy hackin'

choco install erlang --forcex86=true

이렇게 하면 설치는 제대로 되지만 shim이 잘못된 위치(64bit용 위치 즉, \Program Files\ 아래)를 가리키게 되어있어서 오류가 난다.


PS C:\ProgramData\chocolatey> erl

Cannot find file at 'c:\program files/erl9.0/erts-9.0/bin/erl.exe' (c:\program files\erl9.0\erts-9.0\bin\erl.exe). This usually indicates a missing or moved file.


tools/shimgen.exe를 사용해서 다시 생성하면 해결된다.


PS C:\ProgramData\chocolatey\bin> ren erl.exe erl.exe.ERROR

PS C:\ProgramData\chocolatey\bin> ..\tools\shimgen.exe -o C:\ProgramData\chocolatey\bin\erl.exe -p 'C:\Program Files (x8

6)\erl9.0\bin\erl.exe'

PS C:\ProgramData\chocolatey\bin> ren .\werl.exe werl.exe.ERROR

PS C:\ProgramData\chocolatey\bin> ..\tools\shimgen.exe -o C:\ProgramData\chocolatey\bin\werl.exe -p 'C:\Program Files (x

86)\erl9.0\bin\werl.exe'


제목을 'chocolatey에서 shim이 잘못되었을 때 새로 생성하는 방법'으로 할걸 그랬나?


happy hackin'


2018-10-23 추가:

오늘 새로 생긴 박스에 설정하면서 새로 깔아보니 아래와 같은 메시지가 보였다. 이것이 의미하는 바는... 저 5개의 실행파일 모두에 대해서 shimgen을 해 주어야한다는 것이다.

......

Installing erlang...

erlang has been installed.

Added C:\ProgramData\chocolatey\bin\erl.exe shim pointed to 'c:\program files/erl10.0.1/erts-10.0.1/bin/erl.exe'.

Added C:\ProgramData\chocolatey\bin\werl.exe shim pointed to 'c:\program files/erl10.0.1/erts-10.0.1/bin/werl.exe'.

Added C:\ProgramData\chocolatey\bin\erlc.exe shim pointed to 'c:\program files/erl10.0.1/erts-10.0.1/bin/erlc.exe'.

Added C:\ProgramData\chocolatey\bin\escript.exe shim pointed to 'c:\program files/erl10.0.1/erts-10.0.1/bin/escript.exe'.

Added C:\ProgramData\chocolatey\bin\dialyzer.exe shim pointed to 'c:\program files/erl10.0.1/erts-10.0.1/bin/dialyzer.exe'.

......

Erlang NIF 최적화

함수형 언어/Erlang 2017. 3. 20. 10:30 by manywaypark

첨부 문서(원본 소실에 대비해 첨부)는 오래 걸리는 nif function call에 관해 심도있게 고찰한 문서이다.


간단히 요약한다.


0. 전제

NIF의 제약 사항은 아주 빨리 처리를 끝내야한다는 것이다 (보통 1~2 ms)

이유는 native code를 처리할 때는 ERTS의 scheduler가 block되므로 다종다양한, 파악조차 힘든 문제를 겪을 수 있다.

(대표적으로 여러 노드가 통신하는 상황이면 60초 timeout에 걸릴 수 있는데, 처음 경험하면 아주 난감한 상황이 될 것이다)

참고로 function call의 처리가 끝나는 시점은 return value를 받는 시점이다.


1. chunking

말 그대로 조금씩 잘라서 처리하는 것이다. 


2. enif_schedule_nif (+ enif_consume_timeslice)

chunking을 좀더 편하게 해주는 API가 추가된 것이다.


3. dirty schedulers:

task의 성격에 따라 schedule 정책을 달리하는(?) 것이다.

기본적으로 ERTS에 포함되지 않았으므로 이렇게 ERTS compile:

configure --enable-dirty-schedulers

사용:

ErlNifFunc 정의에서 ERL_NIF_DIRTY_JOB_CPU_BOUND, ERL_NIF_DIRTY_JOB_IO_BOUND 등의 flag를 준다.



4. thread 사용(어디서 읽었는데 이 문서는 아닌듯)

nif function은 caller pid 정도만 저장하고 바로 return한다.

worker thread가 오래 걸리는 작업을 처리한 후에 enif_send로 caller process에 전달한다. caller process는 receive해서 결과를 받는다.


14115736879341vinoskioptnativecode.pdf



원본: http://www.erlang-factory.com/static/upload/media/14115736879341vinoskioptnativecode.pdf


happy hackin'



problem:

rebar(엄밀히 말하면 rebar2)에서 rebar3로 업그레이드를 진행중인데, sqerl에서 아래와 같은 오류가 났다.

===> Compiling project

===> Compiling path/to/file.erl failed

path/to/file.erl:none: error in parse transform 'sqerl_gobot': {function_clause,

                                         [{lists,map,

                                           [#Fun<sqerl_gobot.1.114344583>,

                                            undefined],

                                           [{file,lists.erl},{line,1237}]},

                                          {sqerl_gobot,who_types_the_untyped,

                                           1,

                                           [{file,

                                             /path/to/project/_build/default/lib/sqerl/src/sqerl_gobot.erl},

                                            {line,81}]},

                                          {sqerl_gobot,parse_transform,2,

                                           [{file,

                                             /path/to/project/_build/default/lib/sqerl/src/sqerl_gobot.erl},

                                            {line,51}]},

                                          {compile,

                                           '-foldl_transform/2-anonymous-2-',

                                           2,

                                           [{file,compile.erl},{line,932}]},

                                          {compile,foldl_transform,2,

                                           [{file,compile.erl},{line,934}]},

                                          {compile,

                                           '-internal_comp/4-anonymous-1-',2,

                                           [{file,compile.erl},{line,295}]},

                                          {compile,fold_comp,3,

                                           [{file,compile.erl},{line,321}]},

                                          {compile,internal_comp,4,

                                           [{file,compile.erl},

                                            {line,305}]}]}


root cause:

사실 제법 많은 시간을 헤맸는데, 원본 파일이 컴파일 되지 않는 것이었다. 아래 라인을 소스 파일에서 제거하고 돌려보면 컴파일 에러(include 파일을 찾지 못함)가 났다.

-compile({parse_transform, sqerl_gobot}).

rebar2와 rebar3(정확히는 rebar3의 release)의 디렉토리 구조가 달라서 아예 컴파일이 안되는 것이 었다. 

AST구성후 parse transform후에 컴파일을 진행하게 되므로 상기 에러와 같은 이상한 에러가 나온다. 

직접적인 원인은 include가 되지 않아 정상적인 AST가 생성되지 않았는데 그 AST를 조작질(parse trasform)하려니깐 문제가 생긴 것인데... 에러 메시지만으로 알아보기 힘들었다.


solution:

include path 정확히 설정해 준다. release의 root에 rebar.config 파일이 있다면 아래처럼 설정한다 (사실 이거말고 다른 방법도 몇개 존재한다).

{erl_opts, [debug_info

           ,{parse_transform, lager_transform}

           ,{i, "apps/project"}]}.

요점은 parser transform을 요하는 소스 파일이라해도 적용전의 형태에서 컴파일은 되어야만 한다는 것. 

parser transform 관련해서 문제 생기면 transform을 disable하고 컴파일 테스트해보는 것을 추천하고 싶다.


happy hackin'



대량의 동시 접속 처리하기 위한 설정들 모음

ref: http://emqtt.io/docs/v2/tune.html


kerl - erlang installer

함수형 언어/Erlang 2014. 5. 22. 17:59 by manywaypark

아주 간편한 erlang 설치 방법이 있었다. 이걸 여태껏 모르고 있었다니... Orz

kerl이라는 utility를 사용하면 source에서 build하는 것은 누워서 떡먹기다.

또한 여러 버전을 깔고 activate/deactivate 할 수 있다. two thumbs up!!


받기 및 실행권한 주기:

curl -O https://raw.githubusercontent.com/spawngrid/kerl/master/kerl

chmod a+x kerl

kerl이 있는 곳을 PATH에 추가한다 (optional).


아래 내용으로 ~/.kerlrc 파일 생성 (64bit Mac OS X의 경우):

KERL_CONFIGURE_OPTIONS="--disable-hipe --enable-smp-support --enable-threads

                        --enable-kernel-poll  --enable-darwin-64bit"


R15B01 버전 build하기:

./kerl build R15B01 r15b01


설치 및 활성화하기:

./kerl install r15b01 ~/erlang/r15b01

. ~/erlang/r15b01/activate


비활성화:

kerl_deactivate


refs: 

http://docs.basho.com/riak/latest/ops/building/installing/erlang/

https://github.com/spawngrid/kerl


2014-07-15 추가: erlang의 build 환경이 제대로 갖추어지지 않았다면 이렇게...

$ sudo apt-get  build-dep erlang

ref: http://askubuntu.com/questions/21379/how-do-i-find-the-build-dependencies-of-a-package


happy hackin'

framewerk(오타 아님)는 일종의 autotools wrapper이다.

c/c++은 물론이고 javascript와 erlang도 지원하는 점이 맘에든다.

사용법은 참조링크에 쉽고 자세하게 나온다.

간단한 예제를 하나 들자면 erlang project에서 rebar 및 git을 사용할 경우 다음과 같이 한다.

$ fw-init --name myprj --template erlang-rebar --revision git

$ cd myprj

$ ./bootstrap

$ ./configure

$ make

지원되는 버전 관리 도구(revision에서 설정): git, svn, cvs

지원되는 개발 환경(template에서 설정): c, c++, erlang, erlang-rebar, java-mvn


refs: https://code.google.com/p/fwtemplates/


2014-11-11 추가: project configuration(version number 설정 등)은 fw-pkgin/config 파일을 편집한다.


2016-06-07 추가: 원래 프로젝트 페이지는 관리 안된지 좀 오래 인듯. 비교적 최근까지 관리되는 곳은 여기: https://github.com/dukesoferl/fw

또한 빌드 및 사용 법은, ./bootstrap -> ./build (--prefix=/usr/local) -> sudo make install 로 하면 좀더 간편하다.


happy hackin'

nif(c/c++ shared object)를 erlang runtime에 올려서 쓰다보면 gdb를 사용할 일이 생긴다.

/usr/bin/erl은 shell script다.

그 내용을 보고 환경변수만 맞추어주면 된다. 아래처럼 한다.

# (emacs라면, M-x gdb 후에)

gdb --annotate=3 /usr/lib/erlang/erts-5.8.5/bin/beam.smp

......

(gdb) set environment ROOTDIR /usr/lib/erlang

(gdb) set environment BINDIR /usr/lib/erlang/erts-5.8.5/bin

(gdb) set environment EMU beam

(gdb) set environment LD_LIBRARY_PATH /path/to/lib:/usr/local/lib:/usr/lib  # optional, 은밀한(?) 곳에 so가 있다면 설정.

(gdb) cd /path/to/working/dir    # optional, 보통 beam.smp가 있는 곳으로 cwd가 바뀌므로 다시 설정한다.

(gdb) r -- -root /usr/lib/erlang -progname erl -- -home /path/to/home -- -sname optional-node-short-name -pa ./ebin

......

주의할 점은, erlang REPL에 들어가고 나면 마땅히 break point를 설정할 방법이 없으므로 REPL 진입전에 break point를 설정해야 한다는 것이다.


happy hackin'


2014-12-22 추가: 

참고 링크(이게 더 간단한가?) http://blog.dizzyd.com/blog/2009/12/18/running-erl-in-a-debugger/ 

요점은 bin/erl을 이렇게 바꾸고 실행한다.

if [ ! -z "$USE_GDB" ]; then gdb $BINDIR/erlexec --args $BINDIR/erlexec ${1+"$@"} else exec $BINDIR/erlexec ${1+"$@"} fi


erlang + autotools + rebar

tips & tricks/Linux/Unix 2014. 4. 11. 18:18 by manywaypark

항상 멋진 도구를 찾아내고 나면 기쁨 뒤에 후회와 허탈함이 밀려온다.

'좀더 찾아볼걸... Orz'

'이거 해결하려고 쓴 시간이 얼마인가... ㅠㅠ'

여튼 erlang에서 autotools와 rebar등을 묶어줄 뿐만 아니라 .deb package까지도 만들어주는 멋진 놈이 존재하고 있었던 것이다.

(물론 erlang 말고 javascript, c, c++도 지원함)

또한 추가적으로 대부분의 메이저 scm도 지원하며, 빌드번호 등도 관리되는 듯하다. 넘 멋지다.

이젠 잘 쓰는 일만 남았다.


refs: 

http://dukesoferl.blogspot.kr/2008/02/erlang-and-automake.html

https://code.google.com/p/fwtemplates/


happy hackin'


ps. 이런 식으로 쓴다.

$ fw-init --name prj-name --template erlang-rebar --revision git


erlang name clash

함수형 언어/Erlang 2014. 1. 15. 10:29 by manywaypark

code:clash()를 쓰면 이름 충돌에 관한 정보가 나온다.

code:get_path(), code:add_patha(), code:add_pathz() 등으로 조회, 추가 등을 할 수 있다.

erl 수행시 -pa, -pz  등의 옵션을 쓰는 방법도 있다.


ref: http://erlang.org/pipermail/erlang-questions/2012-February/064179.html


happy hackin'

1 2 3 4 
분류 전체보기 (306)
잡담 (20)
함수형 언어 (65)
emacs (16)
java (18)
tips & tricks (154)
사랑 (1)
가사 (0)
독서 (4)
mobile (6)
비함수형 언어 (2)

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

04-18 13:38