CuriousY A world with wonder

Strange: threads not join till the end

| Comment

Appearances

I implement a test process with pytest. The test set interacts with some remote test targets through paramiko. As many test targets are involved, multi-threads are used to do something concurrently. The problem is that the main process sometimes can not terminate successfully (i.e. hangs). When investigating the problem, I also found there are several threads which are not joined to the main thread till the end of the test.

This is so strange because all the multi-threads I used are definitely joined successfully.

Behind the appearance

So there must be some threads generated not by myself.

After calling Transport.start_client method, an extra thread will be generated. Let’s see the definition below:

def start_client(self, event=None):
    """
    Negotiate a new SSH2 session as a client.  This is the first step after
    creating a new `.Transport`.  A separate thread is created for protocol
    negotiation.

    If an event is passed in, this method returns immediately.  When
    negotiation is done (successful or not), the given ``Event`` will
    be triggered.  On failure, `is_active` will return ``False``.

    (Since 1.4) If ``event`` is ``None``, this method will not return until
    negotation is done.  On success, the method returns normally.
    Otherwise an SSHException is raised.

    After a successful negotiation, you will usually want to authenticate,
    calling `auth_password <Transport.auth_password>` or
    `auth_publickey <Transport.auth_publickey>`.

    .. note:: `connect` is a simpler method for connecting as a client.

    .. note::
        After calling this method (or `start_server` or `connect`), you
        should no longer directly read from or write to the original socket
        object.

    :param .threading.Event event:
        an event to trigger when negotiation is complete (optional)

    :raises SSHException: if negotiation fails (and no ``event`` was passed
        in)
    """
    self.active = True
    if event is not None:
        # async, return immediately and let the app poll for completion
        self.completion_event = event
        self.start()
        return

    # synchronous, wait for a result
    self.completion_event = event = threading.Event()
    self.start()
    while True:
        event.wait(0.1)
        if not self.active:
            e = self.get_exception()
            if e is not None:
                raise e
            raise SSHException('Negotiation failed.')
        if event.is_set():
            break

And look at the class inheritance of Transport:

class Transport (threading.Thread, ClosingContextManager):

So the truth is that each paramiko connection will generate an individual thread and this thread lasts all the life period of the paramiko object!

BTW, a known bug of paramiko is the termination of the main thread may cause the Transport threads throw exceptions like below:

Exception in thread Thread-24 (most likely raised during interpreter shutdown):Exception in thread Thread-17 (most likely raised during interpreter shutdown):

Reading <this & Object Prototypes> - 3

| Comment

Chapter 5: Prototypes

Objects in JavaScript have an internal property, denoted in the specification as [[Prototype]], which is simply a reference to another object. Almost all objects are given a non-null value for this property, at the time of their creation.

有点像子类和父类的那种联系嘛。


The default [[Get]] operation proceeds to follow the [[Prototype]] link of the object if it cannot find the requested property on the object directly.

var anotherObject = {
    a: 2
};

// create an object linked to `anotherObject`
var myObject = Object.create( anotherObject );

myObject.a; // 2

同样类似于从子类向父类寻找某个成员的过程。


The top-end of every normal [[Prototype]] chain is the built-in Object.prototype. This object includes a variety of common utilities used all over JS, because all normal (built-in, not host-specific extension) objects in JavaScript “descend from” (aka, have at the top of their [[Prototype]] chain) the Object.prototype object.

类似Python所有新式类都有一个共同的基类object,而object也提供了一些基本的方法供缺省时调用。


myObject.foo = "bar";

If the property name foo ends up both on myObject itself and at a higher level of the [[Prototype]] chain that starts at myObject, this is called shadowing. The foo property directly on myObject shadows any foo property which appears higher in the chain, because the myObject.foo look-up would always find the foo property that’s lowest in the chain.

类似子类成员对父类成员的覆盖。


As we just hinted, shadowing foo on myObject is not as simple as it may seem. We will now examine three scenarios for the myObject.foo = "bar" assignment when foo is not already on myObject directly, but is at a higher level of myObject’s [[Prototype]] chain:

  1. If a normal data accessor (see Chapter 3) property named foo is found anywhere higher on the [[Prototype]]chain, and it’s not marked as read-only (writable:false) then a new property called foo is added directly to myObject, resulting in a shadowed property.
  2. If a foo is found higher on the [[Prototype]] chain, but it’s marked as read-only (writable:false), then both the setting of that existing property as well as the creation of the shadowed property on myObject are disallowed. If the code is running in strict mode, an error will be thrown. Otherwise, the setting of the property value will silently be ignored. Either way, no shadowing occurs.
  3. If a foo is found higher on the [[Prototype]] chain and it’s a setter (see Chapter 3), then the setter will always be called. No foo will be added to (aka, shadowed on) myObject, nor will the foo setter be redefined.

If you want to shadow foo in cases #2 and #3, you cannot use = assignment, but must instead use Object.defineProperty(..) (see Chapter 3) to add foo to myObject.

这就比子类成员覆盖父类成员要复杂很多了。

Read more

Reading <this & Object Prototypes> - 2

| Comment

Chapter 3: Objects

Objects come in two forms: the declarative (literal) form, and the constructed form.

The literal syntax for an object looks like this:

var myObj = {
    key: value
    // ...
};

The constructed form looks like this:

var myObj = new Object();
myObj.key = value;

原来Python里面的字典就是JavaScript里面的对象(😆)。文中建议是使用字典式的创建方式,更方便。


It’s a common mis-statement that “everything in JavaScript is an object”. This is clearly not true.

This is why I like Python.


There are several other object sub-types, usually referred to as built-in objects. For some of them, their names seem to imply they are directly related to their simple primitives counter-parts, but in fact, their relationship is more complicated, which we’ll explore shortly.

  • String
  • Number
  • Boolean
  • Object
  • Function
  • Array
  • Date
  • RegExp
  • Error

These built-ins have the appearance of being actual types, even classes, if you rely on the similarity to other languages such as Java’s String class.

But in JS, these are actually just built-in functions. Each of these built-in functions can be used as a constructor (that is, a function call with the new operator), with the result being a newly constructed object of the sub-type in question.

我的问题是Object也只是一个内置函数吗?(是的,Object是一个函数对象,不但可以调用,还有许多属性。)


The primitive value "I am a string" is not an object, it’s a primitive literal and immutable value. To perform operations on it, such as checking its length, accessing its individual character contents, etc, a String object is required.

Luckily, the language automatically coerces a "string" primitive to a String object when necessary, which means you almost never need to explicitly create the Object form. It is strongly preferred by the majority of the JS community to use the literal form for a value, where possible, rather than the constructed object form.

Consider:

var strPrimitive = "I am a string";

console.log( strPrimitive.length );         // 13

console.log( strPrimitive.charAt( 3 ) );    // "m"

In both cases, we call a property or method on a string primitive, and the engine automatically coerces it to a Stringobject, so that the property/method access works.

即对stringnumberboolean类型调用的任何方法都是会先隐式转换到对应的高级对象再调用其方法。也就是说这几个基本类型是没有任何内置方法的,仅仅根据类型不同划定了不同大小的内存存储而已(类似C++的intdoublechar等)。我的问题是,为何不一开始就把这些都定义为高级对象(这设计不会真的是和C++学的吧)?

Read more

Reading <this & Object Prototypes> - 1

| Comment

Chapter 1: this Or That?

Let’s try to illustrate the motivation and utility of this:

function identify() {
    return this.name.toUpperCase();
}

function speak() {
    var greeting = "Hello, I'm " + identify.call( this );
    console.log( greeting );
}

var me = {
    name: "Kyle"
};

var you = {
    name: "Reader"
};

identify.call( me ); // KYLE
identify.call( you ); // READER

speak.call( me ); // Hello, I'm KYLE
speak.call( you ); // Hello, I'm READER

this指向了函数的调用者,而不是函数自身(C++的this/Python的self指向类(的实例)自身使得类成员之间可以建立连接,这里一个单独的函数显然不需要这个作用)。


The this mechanism provides a more elegant way of implicitly “passing along” an object reference, leading to cleaner API design and easier re-use.

The more complex your usage pattern is, the more clearly you’ll see that passing context around as an explicit parameter is often messier than passing around a this context. When we explore objects and prototypes, you will see the helpfulness of a collection of functions being able to automatically reference the proper context object.

感觉this的作用在JavaScript中有点类似“类”的多态,即根据不同调用者来产生不同的效果,但它比“类”使用范围更广(多态需要基类相同,而这里的调用对调用者没有什么限制)。


It is true that internally, scope is kind of like an object with properties for each of the available identifiers. But the scope “object” is not accessible to JavaScript code. It’s an inner part of the Engine’s implementation.


We said earlier that this is not an author-time binding but a runtime binding. It is contextual based on the conditions of the function’s invocation. this binding has nothing to do with where a function is declared, but has instead everything to do with the manner in which the function is called.

When a function is invoked, an activation record, otherwise known as an execution context, is created. This record contains information about where the function was called from (the call-stack), how the function was invoked, what parameters were passed, etc. One of the properties of this record is the this reference which will be used for the duration of that function’s execution.

JavaScript的this存放在调用栈里(显而易见嘛)。


Chapter 2: this All Makes Sense Now!

function foo() {
    console.log( this.a );
}

var a = 2;

foo(); // 2

In our snippet, foo() is called with a plain, un-decorated function reference. None of the other rules we will demonstrate will apply here, so the default binding applies instead.

规则1:默认情况this指向global对象。


If strict mode is in effect, the global object is not eligible for the default binding, so the this is instead set to undefined.

function foo() {
    "use strict";

    console.log( this.a );
}

var a = 2;

foo(); // TypeError: `this` is `undefined`

严格模式下禁用了默认的this绑定(默认的这个行为我是暂时没看到啥好处,所以,怎么严格怎么来吧)。

Read more

Reading <Scope & Closures>

| Comment

Chapter 1: What is Scope?

In fact, the ability to store values and pull values out of variables is what gives a program state.

简单的概念我们往往会自动忽略,并不会理解到这么深入。


For JavaScript, the compilation that occurs happens, in many cases, mere microseconds (or less!) before the code is executed. To ensure the fastest performance, JS engines use all kinds of tricks (like JITs, which lazy compile and even hot re-compile, etc.) 


Two distinct actions are taken for a variable assignment (e.g. var a = 2;): First, Compiler declares a variable (if not previously declared in the current scope), and second, when executing, Engine looks up the variable in Scope and assigns to it, if found.

简单说就是声明是编译时进行的,赋值是运行时的(这点和Python一样,虽然Python不需要声明,作为对比,C++的赋值是编译时的?)。


function foo(a) {
    console.log( a ); // 2
}

foo( 2 );

Let’s imagine the above exchange (which processes this code snippet) as a conversation. The conversation would go a little something like this:

Engine: Hey Scope, I have an RHS(right-hand side) reference for foo. Ever heard of it?

Scope: Why yes, I have. Compiler declared it just a second ago. He’s a function. Here you go.

Engine: Great, thanks! OK, I’m executing foo.

Engine: Hey, Scope, I’ve got an LHS(left-hand side) reference for a, ever heard of it?

Scope: Why yes, I have. Compiler declared it as a formal parameter to foo just recently. Here you go.

Engine: Helpful as always, Scope. Thanks again. Now, time to assign 2 to a.

Engine: Hey, Scope, sorry to bother you again. I need an RHS look-up for console. Ever heard of it?

Scope: No problem, Engine, this is what I do all day. Yes, I’ve got console. He’s built-in. Here ya go.

Engine: Perfect. Looking up log(..). OK, great, it’s a function.

Engine: Yo, Scope. Can you help me out with an RHS reference to a. I think I remember it, but just want to double-check.

Scope: You’re right, Engine. Same guy, hasn’t changed. Here ya go.

Engine: Cool. Passing the value of a, which is 2, into log(..).

太生动了。


Both LHS and RHS reference look-ups start at the currently executing Scope, and if need be (that is, they don’t find what they’re looking for there), they work their way up the nested Scope, one scope (floor) at a time, looking for the identifier, until they get to the global (top floor) and stop, and either find it, or don’t.

Unfulfilled RHS references result in ReferenceErrors being thrown. Unfulfilled LHS references result in an automatic, implicitly-created global of that name (if not in “Strict Mode”), or a ReferenceError (if in “Strict Mode”).

所以在严格模式下,我们其实不用太区分RHS还是LHS了。(目前看来Scope上和Python不同的地方在于,外部变量需要声明后才能在内部使用(严格模式下),而Python只有在需要对外部变量赋值时才需要使用global来声明,使用并不需要声明。)


Chapter 2: Lexical Scope

There are two predominant models for how scope works. The first of these is by far the most common, used by the vast majority of programming languages. It’s called Lexical Scope, and we will examine it in-depth. The other model, which is still used by some languages (such as Bash scripting, some modes in Perl, etc.) is called Dynamic Scope.

编译原理要补课了。


Global variables are also automatically properties of the global object (window in browsers, etc.), so it ispossible to reference a global variable not directly by its lexical name, but instead indirectly as a property reference of the global object.

window.a

JavaScript冷知识。


If lexical scope is defined only by where a function is declared, which is entirely an author-time decision, how could there possibly be a way to “modify” (aka, cheat) lexical scope at run-time?

JavaScript has two such mechanisms. Both of them are equally frowned-upon in the wider community as bad practices to use in your code. But the typical arguments against them are often missing the most important point: cheating lexical scope leads to poorer performance.

这里说的两种方式一是用eval,一是用with。前者强烈不建议用(eval is evil!),且在严格模式下用eval夹带赋值操作是没有作用的(eval(..) when used in a strict-mode program operates in its own lexical scope)。而后者在严格模式下直接整个就不能用了。


with is typically explained as a short-hand for making multiple property references against an object withoutrepeating the object reference itself each time.

For example:

var obj = {
    a: 1,
    b: 2,
    c: 3
};

// more "tedious" to repeat "obj"
obj.a = 2;
obj.b = 3;
obj.c = 4;

// "easier" short-hand
with (obj) {
    a = 3;
    b = 4;
    c = 5;
}

虽然在严格模式下,with语句被禁了,但还是可以了解下,可以看到with的用处和Python完全不一样。

Read more
| Page 17 of 25 |