'Language'에 해당되는 글 75건

  1. 2017.12.28 [NodeJS] Kill child process executed via 'exec' and 'spawn'
  2. 2017.12.28 [Javascript] Generator 를 이용해서 Callback hell을 벗어나 보기....
  3. 2017.12.28 [Javascript] Understanding 'Prototype' of Javascript
  4. 2017.12.28 [Typescript] decorator example
  5. 2017.05.19 [Bash] 'set -e' inheritance...???
  6. 2017.05.19 [Python] __iter__ method of class at add operator with list...
  7. 2017.03.08 Bash print call stack at ERR(trap)
  8. 2015.10.19 [Java] Java main thread vs. user thread vs. daemon thread.
  9. 2015.10.19 [C/C++] Small tip - Argument passed to main() function.
  10. 2015.09.06 [Python] binding function parameter default value.

[NodeJS] Kill child process executed via 'exec' and 'spawn'

Language/Typescript 2017.12.28 20:48


Node 8.9.0 기준

ChildProcess.exec는 shell을 통해서 command를 수행한다.
https://nodejs.org/api/child_process.html 의 아래 설명 참조.


child_process.exec(command[, options][, callback])
    ...
    shell <string> Shell to execute the command with. Default: '/bin/sh' on UNIX, process.env.ComSpec on Windows. See Shell Requirements and Default Windows Shell.
    ...


그래서 주어진 command는 실제로는 "shell => command"로 수행이 되며, exec(...)에 의해서 return되는 process는 shell process이다.
(주의: user command에 의해 수행되는 process가 아니다!)
따라서, return된 process를 kill 해도 실제 user command의 process가 kill되지는 않는다.

이 문제는, exec대신 'execFile' 혹은 'spawn'을 통해서 해결 가능하다.
아래는 spawn관련 document이다.


child_process.spawn(command[, args][, options])#
    ...
    shell <boolean> | <string> If true, runs command inside of a shell. Uses '/bin/sh' on UNIX, and process.env.ComSpec on Windows. A different shell can be specified as a string. See Shell Requirements and Default Windows Shell. Default: false (no shell).
    ...

즉 spawn은 'shell'을 통하지 않고 바로 수행가능하다.
따라서,

let child = spwn(command[, args], {shell: false})
child.kill()

와 같은 방식은 정상적으로 동작한다.

혹은 execFile 은 기본적으로 shell을 통하지 않으므로, child.kill()이 정상 수행된다.




Trackback 0 : Comment 0

[Javascript] Generator 를 이용해서 Callback hell을 벗어나 보기....

Language/Typescript 2017.12.28 20:47


<<< co.ts >>>
//
// Module to help escape from callback-hell by using semi-coroutine(generator).
//

function co<E, T>(generator: GeneratorFunction,
        callback: (err: E, result: T) => void) {
    function *wrapper(resolve: any, reject: any) {
        let wrapperGenerator: Generator = yield;
        try {
            let result = yield* (<any>generator)(wrapperGenerator);
            resolve(result);
        } catch (e) {
            reject(e);
        }
    }

    new Promise<T>((resolve, reject) => {
        let w = wrapper(resolve, reject);
        w.next(); // run function
        w.next(w);
    }).then(r => {
        callback(<any>undefined, r);
    }, e => {
        callback(e, <any>undefined);
    });
}

export = co;


<< main.ts >>

import co = require('./co');


describe('co', function() {
    it('co success', done => {
        co<string, Array<Number>>(<any> function* (gen: Generator) {
            let path = new Array<Number>();
            path.push(10);
            setTimeout(() => {
                path.push(20);
                gen.next();
            }, 200);
            yield;
            path.push(30);
            return path;
        }, (err, result) => {
            assert.ok(undefined === err
                && 3 === result.length
                && result[0] === 10
                && result[1] === 20
                && result[2] === 30);
            done();
        });
    });

    it('co fails: throw in generator', done => {
        co<string, string>(<any> function* (gen: Generator) {
            setTimeout(() => {
            }, 200);
            if (gen) {
                throw 'error';
            }
            return 'hello';
        }, (err, result) => {
            assert.ok(undefined === result
                && 'error' === err);
            done();
        });
    });

    /*
     * This test gives unexpected error at mocha. But works well at normal environment.
     *
     *
     * (node:41022) UnhandledPromiseRejectionWarning: Unhandled promise rejection...
     * (node:41022) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated....
     * node_modules/mocha/lib/runner.js:690
     * err.uncaught = true;
     *            ^

     * TypeError: Cannot create property 'uncaught' on string 'error'
     *     at Runner.uncaught ...
     *     ...
     *

    it('co fails: Generator.throw', done => {
        let path = new Array<Number>();
        co<string, string>(<any> function* (gen: Generator) {
            setTimeout(() => {
                gen.throw!('error');
                path.push(10);
                return;
            }, 200);
            return 'done';
        }, (err, result) => {
            assert.ok(undefined === result
                && 'error' === err
                && 1 === path.length);
            done();
        });
    });
    */
});


Trackback 0 : Comment 0

[Javascript] Understanding 'Prototype' of Javascript

Language/Typescript 2017.12.28 20:38


< 좋은 link >
http://insanehong.kr/post/javascript-prototype/



< From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new >

The new operator creates an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

...

When the code new Foo(...) is executed, the following things happen:

A new object is created, inheriting from Foo.prototype.
The constructor function Foo is called with the specified arguments, and with this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)


< From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype >

...

Object.prototype.constructor
    Specifies the function that creates an object's prototype.

...


--------
즉, 'prototype' property는, 결국 'new' operation에서 object inherit을 위해 사용되는 reserved property이고, instance의 prototype chain은 [[Prototype]](de-facto __proto__) 에 의해 관리된다.

이상에서 다음을 알수(유추할수?) 있다.
- 'prototype' property 는 일반적인 object 이다. (*1)
    : constructor function을 가지는 단순한 object (javascript의 'new' operation protocol을 맞추기 위한 suger object 정도로 밖에 보이지 않는다.)
- 'prototype' property 는 'constructor' function을 가진 object에 한해서만 의미가 있다.
- [[Prototype]]은 'prototype' object 를 가리킨다.

=====================
확실한 이해를 위해 'new' operation의 동작을 확인해 보자.(Tested on console of Chrome-63)


> function A(name) {
    this.date = Date.now();
    this.x = 'Proto';
    this.name = name;
}
undefined

> a = new A('a')
A {date: 1514262817152, x: "Proto", name: "a"}

> b = new A('b')            <= date 값이 매번 달라진다.
A {date: 1514262824795, x: "Proto", name: "b"}

> A.prototype                <= constructor만을 가지는 아주 단순한 object
{constructor: ƒ}
    constructor: ƒ A(name)
    __proto__: Object        <= Object Prototype


> c = Object.create(A.prototype);    <= 단순하게 constructor를 상속하는 과정이라고 생각할 수도 있다.
A {}

> c.constructor('c')            <= Prototype의 constructor를 새롭게 생성된 object에 binding해서 수행한다. (Same with, c.__proto__.constructor.call(c, 'c'))
undefined                   Note: binding of 'this' keyworkd (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)
                       Note: c.__proto__.constructor('c') <= 잘못된 수행. prototype object 자체를 더럽히게 된다.
> c.constructor === c.__proto__.constructor
true

> c
A {date: 1514262907466, x: "Proto", name: "c"}


Trackback 0 : Comment 0

[Typescript] decorator example

Language/Typescript 2017.12.28 20:36


Working environment:
OS: Linux 4.4.0-104-generic #127-Ubuntu SMP Mon Dec 11 12:16:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
nodejs: 8.9.1
typescript: 2.6.2




<< class decorator >>


(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Class decorator
//
///////////////////////////////////////////////////////////////////////////////
/**
 * See ClassDecorator type at lib.es5.d.ts
 * @param ctor constructor function. Prototype of constructor function
 *               is object for class-definition.
 */
function log<T extends Function>(ctor: T): T | void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);
    console.assert('function' === typeof(ctor));
    console.log('%o', ctor);
    let newConstructor: any = function (...args: Array<any>) {
        console.log('New: ' + ctor.name);
        let o: any = new (<any>ctor)(...args);
        // this is new constructor. So, '_test' is shown at console.log(<instance>)
        o._test = 'mytest';
        return o;
    };
    return newConstructor;
}

@log
class Person {
    constructor(
        public name: string,
        public surname: string
    ) { }

    get myname() {
        return this.name;
    }

    fullname(nick: string) {
        return `${this.name} ${this.surname} : ${nick}`;
    }
}

let p = new Person('name', 'surname');
// console.log('%o, %O', p, p);
console.assert(p.name === 'name');
console.assert(p.myname === 'name');
console.assert(p.fullname('N') === 'name surname : N');
console.assert((<any>p)._test === 'mytest');


///////////////////////////////////////////////////////////////////////////////
//
// Class decorator with argument.
//
///////////////////////////////////////////////////////////////////////////////
function logArg(nick: string) {
    return function<T extends Function>(ctor: T): T | void {
        let newCtor: any = function (...args: Array<any>) {
            // console.log('New: ' + fconstructor.name);
            let o: any = new (<any>ctor)(...args);
            o.nick = nick;
            return o;
        };
        return newCtor;
    };
}

@logArg('nick')
class Person2 {
    constructor(
        public name: string
    ) { }

    fullname(age: number) {
        return `${this.name} ${(<any>this).nick} : ${age}`;
    }
}

let p2 = new Person2('name');
// console.log(p);
console.assert(p2.name === 'name');
console.assert(p2.fullname(18) === 'name nick : 18');
console.assert((<any>p2).nick === 'nick');


///////////////////////////////////////////////////////////////////////////////
})();









<< method decorator >>

(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Member decorator
//
///////////////////////////////////////////////////////////////////////////////

/**
 * See MethodDecorator at lib.es5.d.ts for detail types.
 * @param target class(prototype of class-constructor) where this method belongs to
 * @param key name of method
 * @param descriptor method(function)-property descriptor
 */
function log(
    target: any, key: string | symbol, descriptor: TypedPropertyDescriptor<any>
): TypedPropertyDescriptor<any> | void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);

    console.assert('fullname' === key);

    // This is ONLY FOR DEMO and EXAMPLE! - NOT RECOMMENDED!
    // Add new property to prototype of class-constructor.
    // (applied to all class instance!)
    target['newattr'] = 'hello';

    // save a reference to the original method this way we keep the values currently in the
    // descriptor and don't overwrite what another decorator might have done to the descriptor.
    if (descriptor === undefined) {
        descriptor = Object.getOwnPropertyDescriptor(target, key)!;
    }

    //editing the descriptor/value parameter
    let orig = descriptor.value;
    descriptor.value = function () {
        console.log(`Called: ${key}`);
        return orig!.apply(this, arguments);
    };

    return descriptor;
}


class Person {
    constructor(
        public name: string,
    ) { }

    get myname() {
        return this.name;
    }

    @log
    fullname(newname: string, nick: string) {
        this.name = newname;
        return `${this.name}:${nick}`;
    }
}

let p = new Person('name');
let p2 = new Person('name2');
// console.log(p.fullname('newname', 'nick'));
console.assert('name' === p.myname);
console.assert('name2' === p2.myname);
console.assert('hello' === (<any>p).newattr);
console.assert('hello' === (<any>p2).newattr);
console.assert('newname:nick' === p.fullname('newname', 'nick'));
console.assert('newname' === p.myname);
console.assert(`hello` === (<any>p).newattr);

console.log(p);

///////////////////////////////////////////////////////////////////////////////
//
// Member decorator with argument
//
///////////////////////////////////////////////////////////////////////////////

// Same way with class decorator.

///////////////////////////////////////////////////////////////////////////////
})();





<< parameter decorator >>

(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Parameter decorator
//
///////////////////////////////////////////////////////////////////////////////

/**
 *
 * @param target class(prototype of class-constructor) where this method belongs in
 * @param key name of method where this parameter belongs to
 * @param index parameter position in function - stars at 0(the first parameter).
 */
function log(target: any, key: string | symbol, index: number): void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);

    console.assert('fullname' === key);
    console.assert(1 === index);
}


class Person {
    constructor(
        public name: string,
    ) { }

    get myname() {
        return this.name;
    }

    fullname(newname: string, @log nick: string) {
        this.name = newname;
        return `${this.name}:${nick}`;
    }
}

let p = new Person('name');
// console.log(p.fullname('newname', 'nick'));
console.assert('newname:nick' === p.fullname('newname', 'nick'));
console.assert('newname' === p.myname);

///////////////////////////////////////////////////////////////////////////////
})();






<< property decorator >>

(() => {
///////////////////////////////////////////////////////////////////////////////
//
// Property decorator
//
///////////////////////////////////////////////////////////////////////////////

/**
 *
 * @param target class(prototype of class-constructor) where this method belongs in
 * @param key name of method where this parameter belongs to
 */
function log(target: any, key: string | symbol): void {
    // decorator is called with 'this' bound to global-object,
    console.assert(undefined !== this.console);
    console.assert(console === this.console);
    console.assert('name' === key || 'obj' === key);

    let internalKey = `$${key}`;
    // property getter
    let getter = function () {
        console.log(`Get: ${key} => ${this[internalKey]}`);
        return this[internalKey];
    };

    // property setter
    let setter = function (newVal: any) {
        console.log(`Set: ${key} => ${newVal}`);
        this[internalKey] = newVal;
    };

    // Delete property.
    if (delete target[key]) {
        console.assert(undefined === target[`$${key}`]);
        // Create new property with getter and setter
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
    }
}

class Person {
    @log
    public name = 'init';
    @log
    public obj = {};

    constructor(name: string) {
        this.name = name;
    }

    get myname() {
        return this.name;
    }

    fullname(newname: string, nick: string) {
        this.name = newname;
        return `${this.name}:${nick}`;
    }
}

let p = new Person('name');
p.name = 'hello';
p.obj = {a: 1};

console.assert((<any>p)['$name'] === p.name);
console.assert((<any>p)['$obj'] === p.obj);
console.assert('newname:nick' === p.fullname('newname', 'nick'));
console.assert('newname' === p.myname);

// console.log('%o', p);

///////////////////////////////////////////////////////////////////////////////
})();


Trackback 0 : Comment 0

[Bash] 'set -e' inheritance...???

Language/Bash 2017.05.19 20:33



======================================================

       −e    When this option is on, when any command fails (for any of the reasons listed in Section 2.8.1, Consequences of Shell Errors or by  return‐
             ing an exit status greater than zero), the shell immediately shall exit with the following exceptions:

              1. The  failure  of any individual command in a multi-command pipeline shall not cause the shell to exit. Only the failure of the pipeline
                 itself shall be considered.

              2. The −e setting shall be ignored when executing the compound list following the while, until, if, or  elif  reserved  word,  a  pipeline
                 beginning with the !  reserved word, or any command of an AND-OR list other than the last.

              3. If  the exit status of a compound command other than a subshell command was the result of a failure while −e was being ignored, then −e
                 shall not apply to this command.

             This requirement applies to the shell environment and each subshell environment separately. For example, in:

                 set -e; (false; echo one) | cat; echo two

             the false command causes the subshell to exit without executing echo one; however, echo two is executed because  the  exit  status  of  the
             pipeline (false; echo one) | cat is zero.

==========================


#!/bin/bash

set -e

function myf {
    echo "Enter myf"
    false
    echo "Exit myf"
}

echo "Start"
myf
echo "End"



$ ./x.sh
Start
Enter myf


=======================

#!/bin/bash

set -e

function myf {
    echo "Enter myf"
    false
    echo "Exit myf"
}

echo "Start"
myf || true
echo "End"


$ ./x.sh
Start
Enter myf
Exit myf
End


========================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    exit 2
}

function test {
    a=$(myf)
    echo "TEST DONE"
}

a=$(test)
echo "DONE"

$ ./x.sh
myf
DONE


===========================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    exit 2
}

a=$(myf)
echo "TEST DONE"



$ ./x.sh
myf


====================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    false
    echo "myf DONE"
}

a=$(myf)
echo "DONE"



$ ./x.sh
myf
DONE


=======================

#!/bin/bash

set -e

function myf {
    echo 'myf' >&2
    false
    echo "myf DONE"
}

function test {
    a=$(myf)
    echo 'test DONE'
}

a=$(test)
echo "DONE"


$ ./x.sh
myf
DONE


'Language > Bash' 카테고리의 다른 글

[Bash] 'set -e' inheritance...???  (0) 2017.05.19
Bash print call stack at ERR(trap)  (0) 2017.03.08
Trackback 0 : Comment 0

[Python] __iter__ method of class at add operator with list...

Language/Python 2017.05.19 20:32


class L(object):
    def __init__(self, lst):
        self.l = lst

    def __iter__(self):
        print('iter..')
        for l in self.l:
            yield l

    def __str__(self):
        return ' '.join(self.l)


l1 = L(['1', '2', '3'])
l2 = []
ll2+= l1
print(' '.join(l2))


$ ./a.py
iter..
1 2 3



Trackback 0 : Comment 0

Bash print call stack at ERR(trap)

Language/Bash 2017.03.08 22:03


At head of script file:

(CODE-1)
trap 'on_error "${FUNCNAME[@]} ${BASH_LINENO[@]} $LINENO"' ERR
trap 'on_exit' EXIT

Someone may wonder why don't write code like below because it is easier to handle arguments.

(CODE-2)
trap 'on_error "$LINENO ${FUNCNAME[@]} ${BASH_LINENO[@]}"' ERR
trap 'on_exit' EXIT

I don't know there is any documented information related with this. But, results of my experiments are saying that (CODE-2) doens't work as expected.
In case of (CODE-2), my test shows that only latest function-stack information is passed to 'on_error' trap function.
I don't have any idea about the reason. More investigation is required for this.
But anyway, (CODE-1) works well.
So, you can use those arguments to print function call stack at bash.
You may need to use 'BASH_SOURCE' array too, if your bash uses other files, too.



And there is one interesting case. See follow code.

<< Test environment >>
bash: GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
OS: Linux XXXX 4.4.0-64-generic #85-Ubuntu SMP Mon Feb 20 11:50:30 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

-------------------------- TEST-1 -----------------------------
<< a.sh >>
function on_err() {
    echo "error"
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

myval=$(echo u | grep p)  # global variable


$ bash -eE a.sh
error
exit

-------------------------- TEST-2 -----------------------------

<< a.sh >>
function on_err() {
    echo "error"
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

function f0() {
    local myval=$(echo u | grep p)  # local variable in function
}

f0

$ bash -eE a.sh
exit

---------------------------------------------------------------

Even if errtrace is enabled(-E option), 'error' is NOT printed at TEST-2.
Then, is this means 'ERR' is NOT trapped at TEST-2? That is, does 'on_err' not executed?
Let's have a look following code.

-------------------------- TEST-3 -----------------------------

<< a.sh >>
function on_err() {
    echo "error"
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

function f0() {
    myval=$(echo u | grep p)  # NOT local variable anymore.
}

f0

$ bash -eE a.sh
error
exit

-------------------------- TEST-4 -----------------------------

<< a.sh >>
function on_err() {
    echo "error" 1>&2  # echo to standard error.
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

function f0() {
    local myval=$(echo u | grep p)  # local variable
}

f0

$ bash -eE a.sh
error
exit

-------------------------- TEST-5 -----------------------------


function on_err() {
    echo "error" 1>&2  # echo to stderr
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

myval=$(echo u | grep p)  # assign to global variable.


$ bash -eE a.sh
error
error
exit


-------------------------- TEST-6 -----------------------------


function on_err() {
    true  # There is no echo
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

myval=$(echo u | grep p)  # asign to global variable


$ bash -eE a.sh
exit

---------------------------------------------------------------

It's very interesting, isn't it?
Further investigation will be continued for this issue.



'Language > Bash' 카테고리의 다른 글

[Bash] 'set -e' inheritance...???  (0) 2017.05.19
Bash print call stack at ERR(trap)  (0) 2017.03.08
Trackback 0 : Comment 0

[Java] Java main thread vs. user thread vs. daemon thread.

Language/Java 2015.10.19 23:01

StackOverlow 의 아래 답변을 참고하자.

http://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java


정리하면, JVM은 main thread가 끝나더라도, 아직 수행중인 다른 thread - non daemon thread(user thread) - 가 있다면, 중지되지 않는다.

즉, process가 계속해서 돈다.

C/C++ 처럼, main thread가 exit될 때 process를 종료시키려면, 모든 child thread 속성을 daemon thread로 설정해야 한다.


Thread t = new Thread(...)

t.setDaemon(true);


남아 있는 모든 thread가 Daemon thread일 경우, JVM은 중지된다.

다만, 이런식으로 thread가 급작스레 종료하는 것은 상당히 불안정한 결과를 가져 올 수 있으므로 주의해야 한다.


다시 말하면, 단 하나라도 종료되지 않은 user thread (non-daemon thread) 가 존재할 경우, JVM은 종료되지 않고, 모든 다른 thread (Daemon thraed 포함)역시 계속해도 수행된다.



Trackback 0 : Comment 0

[C/C++] Small tip - Argument passed to main() function.

Language/C&C++ 2015.10.19 22:56

In general, main function is used as below.


int main(int argc, const char *argv[]) {

}


But, it can be expanded like below


int main(int argc, const char *argv[], const char **envp) {

        while (*envp) {

                printf("%s\n", *envp++);

        }

}


By this way, we can use environment variables easily.

=> This matches parameters of execle() and execvpe() at Linux.



'Language > C&C++' 카테고리의 다른 글

[C/C++] Small tip - Argument passed to main() function.  (0) 2015.10.19
[C/C++] Template with value  (0) 2015.04.28
[C/C++] sizeof array  (0) 2015.03.19
[Macro] '##' macro operator  (0) 2015.02.11
'malloc' and 'Segmentation fault'  (0) 2014.07.25
[GCC] Initialize array...  (0) 2014.07.25
Trackback 0 : Comment 0

[Python] binding function parameter default value.

Language/Python 2015.09.06 06:11

function 을 define하는 시점에 default value를 binding한다.

(Spec.을 찾아본건 아니고.. 시험적으로...)



[test.py]


_DEFVAL = 10


def set_def(val):

    global _DEFVAL

    _DEFVAL = val


def prdef(val=_DEFVAL):

    print '+++ ' + str(val) + '\n'


prdef()

set_def(0)

prdef()


============== outputs ==============

+++ 10


+++ 10


Trackback 0 : Comment 0