在加拿大续签美国F1签证

刚从使馆回来,做个记录。

因为四月半要出去开会,F1签证4月10号到期,于是需要申请个新的F1签证。

因为最近有deadline,时间不多,不打算回国搞签证,于是打算就近搞一个。鉴于纽约到加拿大比较近,于是就决定去加拿大搞。

首先是搞定加拿大签证。有F1签证的申请加拿大多次入境旅游签证非常容易,有空我另外写一个。

然后就是到加拿大申请美国签证,参考:http://blog.renren.com/share/229659567/3764006300/

在线申请

在https://usvisa-info.com/en-CA/selfservice/login注册,然后填基本信息。选类型,反正我是非加拿大居民-申请F1(College and University)签证。我打算在多伦多搞,于是选多伦多使馆。里面有个选取护照的Loomis分店的选项,其实无所谓,因为非加拿大居民的貌似都会让你去使馆取。

之后要交签证费,160USD…… 在线交就可以了,交完了可以打个receipt出来,不过其实没人看。现在交签证费的方法和参考里的已经不一样了。

交完签证费才能预约。预约其实没有文中说的那么麻烦,至少我看的那几天,最近的预约都只有1~2天。但是貌似不一定会放出之后一段时间的,比如说我这周看,下周前几天都有,再下周就没有了。最后我是在签证前两周约的。不知道是放出来晚,还是有某些人屯着到最后没出手才放出来的。参考里那个黄牛网站现在可贵了,其实没啥必要。

个人信息里是要填DS-160号和SEVIS号的。SEVIS号就是I20右上角那个Nxxxxxxxxxx号码。DS-160要预先填好,就和填普通的DS-160差不多,签证地点当然是选预约的地方。

签证当天

我约的早上8点,估计大概是当天早上8点多了才到。整个签证过程就是若干个排队过程,一个一个来说。

首先是门外排队,会有大妈过来问你约的几点,你来太早的话她会叫你晚点再来。

门卫会检查签证预约和护照,然后安检。和飞机差不多,过个安全门,然后上下扫一遍。貌似不能带手机/各种电子产品/打火机/电子钥匙/…… 反正弄个文件夹装必要材料,然后两手空空过去就行了。

之后就是在使馆里面排队。有人会检查你的DS-160和护照,再之后就进入有签证窗口的房间了。这个窗口发一个蓝色文件夹,说里面只能放DS-160和护照。

一共有10个签证窗口。目前这个队列的处理窗口是1-4。这个窗口检查基础信息,包括护照,DS-160和I-20。我问要不要SEVIS费收据,他说不用,我能查到你已经交了…… 他会把你的I-20放入那个蓝色文件夹,然后让你排下一个队。他在我DS-160确认页上做了若干标记,比如我目前在加拿大身份是A,交了SEVIS FEE等等。他说你这照片不太行啊,啥时候照的。我说去年十月。他说好吧。(其实貌似更早一些,要求六个月之内……)

这个队伍由窗口9-10处理,主要就是按指纹,非常快。过了之后给你个号码,等叫号。这时候可以做在房间中的椅子上等。

这个最终的队伍由窗口5-8处理。我进入房间大概是8:25,那个时候大约在处理V008的样子,我排到了V037。等了挺长一段时间,大约8:50左右,轮到我。

(以下英语对话)

签证官:你要干啥?

我:我要回去继续读PhD。

签证官:为啥跑加拿大来签。

我:最近赶deadline,比较忙。

签证官:你签证过期了回国也没有问题嘛。

我:我四月份要去开会。

签证官:哪儿?

我:阿姆斯特丹。

签证官:哦,我理解了……

签证官:你简历呢?

我:(给简历)

签证官:你导师叫啥?

我:xxx(给导师简历)

签证官:你搞啥的呀?

我:计算机科学。

签证官一直在打字…… 把导师简历还给我了……

签证官:你有过Program Change嘛?

我:没……

签证官:你2011年开始读的?

我:是啊……

签证官:不好意思,你导师叫啥?

我:(给导师简历……)

我:要成绩单么?

签证官:不用。

过会他就弄了个贴纸,揭了一部分贴护照上,剩下的给了我,说明天下午3-4点来取,然后就完事了。

出来大约是9点左右,还是挺快的。

总的来说,需要的材料有:

× 护照

× I-20,有ISSO最近的签名

× DS-160确认页

× 签证预约确认页

× 我和导师的简历(我就打了个网页……)

既然那么快,看来要不是过了要不是拒了…… 明天再看吧……

另外,我带了没人要的材料有:Study Plan,SEVIS FEE收据,成绩单,在读证明,签证费收据,银行账单,I-94号……

取护照

第二天下午3点多,我到了使馆。这次都不用安检,所以可以带各种电子产品。直接把之前面试官给的一个小条给门口的窗口,过会他就给了我护照和I-20,上面有了新的签证~ 其实就花了两天就搞定了。

关于那个小条,上面有若干说明:
× 只要有了这个小条,谁都能取! // 意思是不要掉了嘛…… 不过你护照在使馆,的确没啥可以证明身份的……
× 这只是让你取护照,并不说明签证过了! // 反正那么快不是据了就是过了……

最后,多谢Nuk收留!

用Python Descriptor弱智了一把

Python Descriptor是个有意思的功能,类似于c++里面的重载operator=和operator T,可以在你访问这个对象的时候,调你定义的__get__(),把返回值作为访问结果,在你给对象赋值的时候,调你的__set__()。

昨晚大约是在搞这么一个类:

class Field(object):
    def __get__(self, obj, objtype):
         ....
    def __set__(self, obj, val):
         ....
 
class Data:
    x = Field()
 
d = Data()

然后在访问d.x的时候,没啥问题,__get__被调用了;但是给d.x赋值的时候,__set__没被调用,只是貌似给d搞上了一个域叫x,之后再访问d.x也不会调__get__了……

在折腾了若干时间之后,最后发现问题特别弱智:Data不是new-style class。只要改成Data(object)就好了……

 

虽然是我弱智吧,这个语言方面也有问题吧…… 既然old-style class不支持Descriptor,为啥__get__能用__set__却不行…… 而且也没个警告之类……

关于错误信息和bug报告

有时候如果你什么错误信息都不输出,那碰到bug的人会去找相关原因;但是如果你输出了一些错误信息,人们可能会误以为那就是bug的原因。

具体来说,例如这个bug rep:

https://bugzilla.mozilla.org/show_bug.cgi?id=833117

简单来说就是很多人碰见了firefox/thunderbird crash。并且他们看见了那么一个错误信息:

GLib-CRITICAL **: void g_slice_set_config(GSliceConfig, gint64): assertion `sys_page_size == 0' failed

然后他们就认为crash是因为这个错误信息引起的。

但其实那个信息只是一个warning,具体来说就是初始化某个组件的时候检查是不是已经初始化过了,如果初始化过了就给个warning并且返回。

所以这些人crash的原因可能各不相同。但是因为看见了一个公共的warning,好多人就跑来”confirm”这个bug了。

如果你啥都不说,或者说这是个warning而不是CRITICAL错误,那多半人们会意识到有别的问题,然后贴stack trace之类,而不是都觉得“我也有这个问题”……

DTrace

这两天搞了一把DTrace,貌似还挺有意思的。

DTrace是个动态跟踪工具,可以在动态环境下向内核/程序中插入探头(probe),收集处理以及显示一些信息。

其实本来搞DTrace是为了一个FreeBSD的bug。搞chromecast的时候发现,IP multicast的目标mac不对。不过后来分析代码大致定位到了出问题的文件,然后在最新代码里发现这个bug已经修了(PR 185395),于是纯粹就是学习DTrace了。

一开始在我的机子上DTrace还跑不起来,后来发现是因为我跑的UEFI分支里的内核路径有些特别,于是DTrace找不到符号。打了个补丁(dt_kernel_path.patch)之后,dtrace终于能用了。

DTrace脚本的主体是一堆事件处理函数。跑DTrace脚本的时候,系统碰到某个符合的事件,就调用对应的函数。这些函数用D语言(不是那个D语言,是DTrace自己的一种语言)写成,语法和C差不多。基本的赋值/比较都能干,不过没有循环,也没有if/then/else。能控制流程的,基本上就是每个事件自带的条件,和三元操作符,也就是?:。

虽然前面那个bug是修了,我还是搞了个简单脚本来试DTrace。我希望观察arpresolve函数的参数和返回结果,也就是那个返回IP对应mac地址的函数。

arpresolve的原型是

int
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, struct llentry **lle)

我希望查看dst里的ip地址,和desten里返回的mac地址。

DTrace脚本如下:

fbt::arpresolve:entry
/execname == "ping" && arg4 != 0/
{
ip = ((struct sockaddr_in *)arg3)->sin_addr.s_addr;
a = (ip & 0xff000000) >> 24;
b = (ip & 0xff0000) >> 16;
c = (ip & 0xff00) >> 8;
d = ip & 0xff;
a4 = (unsigned char *)arg4;
printf("%s %d.%d.%d.%d", execname, d, c, b, a);
}
 
fbt::arpresolve:return
/execname == "ping" && a4 != 0/
{
printf("%s %02x.%02x.%02x.%02x.%02x.%02x", execname, a4[0], a4[1], a4[2], a4[3], a4[4], a4[5]);
}

这里定义了俩probe,一个在arpresolve的入口(entry),还有一个在返回的时候触发。probe的名字有四个部分:

<provider>:<module>:<function>:<name>

provider就是提供这个probe的组件,例如fbt就是Function Boundary Tracing,其他还有syscall追踪system call的调用等。fbt可以追踪几乎内核里所有函数的调用……

module和function确定了包含这个probe的函数。module是模块名,function是函数名。如果一个部分为空(例如这里的module),那相当于*。

name就是这个特定probe的名字,这里entry和return都是。

第一个probe其实完整名字是fbt:kernel:arpresolve:entry,最简单弄成::arpresolve:entry也可以,反正没有别的。

每个probe还能限制触发条件,例如这里的execname == “ping” && arg4 != 0。这个稍微可以弥补一些没有if的缺陷。

在fbt的entry probe中,arg0, arg1…可以用来访问参数,而在return那里,arg0有返回地址(用以区分是哪个return返回的),arg1有返回值。

据说args[i]可以访问带类型的参数,但是我没试成…… 所以这里弄来arg3, arg4强转成了参数类型。DTrace会读取内核里的类型信息,所以各个数据类型直接就能用,这里就不用自己定义sockaddr_in了。转完之后,直接打出来就可以了。

因为在return那边没法读取参数,在entry里我先存了起来。

存了脚本,用dtrace -s就可以跑了。跑出来大概是这样:

> sudo dtrace -s arp.d
dtrace: script ‘arp.d’ matched 2 probes
CPU     ID                    FUNCTION:NAME
  1  20699                 arpresolve:entry ping 239.255.255.250
  1  20700                arpresolve:return ping 01.00.5e.7f.ff.fa
  3  20699                 arpresolve:entry ping 239.255.255.250
  3  20700                arpresolve:return ping 01.00.5e.7f.ff.fa
  1  20699                 arpresolve:entry ping 239.255.255.250
  1  20700                arpresolve:return ping 01.00.5e.7f.ff.fa
^C

当然这个是已经修完了的,修之前ip是网关的ip,mac变成了网关IP根据multicast对应规则转换成mac的结果,例如ip是192.168.1.1,mac是01.00.5e.28.01.01,总之很诡异…… 其实multicast情况下mac应该是用dest ip转的,那个修正也就是修了这个。

DTrace看上去挺有用的,对调试来说简直是静态调试的理想环境,插入调试语句都不用中断运行,也不用担心调试语句写错导致系统crash,还可以访问符号,大大加快调试速度。profiling应该也挺有用,不过我还没研究。

不过没有循环我倒是觉得可能会造成一些麻烦,例如在链表里找东西之类就不好找了。估计还是为了安全性验证和效率考虑吧,不过如果信得过的话,允许程序员用也未尝不可啊。

DTrace一开始是Solaris搞的,后来Mac和FreeBSD都port了一份过来。根据布总的教导,各个系统都有,windows下面有个可以处理SQL语句的,Linux虽然官方内核没有,但是有一堆第三方的。