Repetitive Strain Injury

Repetitive Strain Injury 重复性劳损

https://web.eecs.umich.edu/~cscott/rsi.html
上面这篇文章是我读过的最好的关于RSI的文章。

我与RSI的对抗历史:
2002年开始,右手指头疼,发现与用鼠标有关。当时有人发明了立式鼠标,于是买来用,结果发现效果适得其反。据发明人的解释,右手放在桌面上,自然的状态是手心向左。而在用鼠标时,手心却向下。这样就长期处于非自然状态下,会导致问题。说得似乎有道理。于是我就买了。结果一用,发现,尽管手的状态保持在“自然状态”,但由于鼠标在左边,而不是下边,点击时力度必须相当大才行,结果是为了解决一个问题却带来另外一个问题,一个更大的问题。
由于疼痛并不严重,当时并没有将其当一回事,再也没有采取任何措施防止疼痛加重。
到了2008年,情况越来越严重。终于有一天,无法工作了。右手食指,中指都疼。按鼠标用不上力。表面看去,手没有任何异常。非常奇怪的是,干任何事都没有问题,除了按下鼠标!例如用筷子吃饭,没有任何不适,没有任何疼痛和症状,但是一碰鼠标,中指根部剧痛。
不得已,只好换用左手。刚开始很不灵巧,不过,过了一段时间,左手就适应了。
不过我知道,左手发展到右手那种地步,是迟早的事。
怎么避免呢?
我采取的办法:
0. 桌椅绝对不能凑合。
1. 用苹果的触摸板来代替鼠标。遗憾的是这个只能在macos下用。在Windows下它功能不全,无法完全代替鼠标。
2. 用wacom的数位板和手写笔,曾经买过两个,办公室和家里各有一个。用起来还行,但效率较低。毕竟不是鼠标,用其代替鼠标,不那么方便。必须双手操作才行。
3. 声控。从美国邮购了一套声控软件。结果发现非常不实用,识别率太低了,试了试放弃。我的目标其实很简单,你只要能听懂我有限的指令就行了。我的需求是,你提供自定义配置,只识别特定的话语并将其翻译成鼠标动作或键盘操作。但该软件没有这样的功能,它的目标在英语听写上。
4. 脚控。我的问题主要在用鼠标上,右手不听使唤,最严重的时候中指无力按下鼠标按键,移动倒不成问题。因此我最基本的需求是:不动手按下鼠标。买过脚控键盘,三个大按钮,可自定义功能。刚开始时我将其定义成鼠标左中右键,后来三个全部都定义成了左键(因为经常一脚同时踩中两键)。用了一段时间,发现腿开始疼,赶快放弃。
5. 尽量少用手。过去上网下棋,常常昼夜奋战,现在基本不下了,偶尔下下,使用触摸板和iPad来操作。
6. 使用AntiRSI软件,其实就是提醒功能,这些软件会在你工作持续一段时间后提醒你休息一会。

openssl_uplink no openssl_applink

调用PEM_read_RSAPrivateKey时程序直接退出,跟踪发现,执行到了一个unimplemented(),此函数调用OPENSSL_showfatal后就exit了
fatal内容如下:
openssl_uplink no openssl_applink

原因:
openssl 在一些文件I/O时不用标准的C库函数,而是自己用了22个函数代替,例如 在打开文件时不直接使用 fopen, 而是使用 UP_fopen
但是在libeay32.dll中并没有实现这些函数。它要求调用者来实现,反过来供自己使用。调用者怎么实现呢?这个openssl倒是已经准备好了,调用者需要将applink.c添加到自己的工程项目中,重新编译即可。

在applink.c里面,我们看到,UP_fopen还是#include使用标准的C库函数。
为什么不直接fopen,而要绕这么大一个圈子呢?
我们姑且假设openssl有充分的理由这么做,那么第2个问题是:
为什么不直接在libeay32.dll中实现这22个函数,而要调用者实现?

第1个问题,搜索了一下,发现了一个答案:

https://github.com/openssl/openssl/pull/1356

Mixing threading models is only one particular case. I mean issue is wider than that. Intention was to facilitate mixing different compilers and/or versions, or even compiler flags. I mean say you want to compiler your application with debugging flags. Without applink you’d have to recompile even OpenSSL dlls with same flags… Or consider I’ve got dll from somebody else, without applink you’d have to figure out which compiler version was used and use same. With applink you can use any compiler, not even from same vendor. Once again, if you use interfaces that actually rely on applink. As correctly pointed out those accepting FILE * and Unix-like fd from application. And once again, recommendation is avoid those in new application code.

感到理由不那么充分

继续往下读

threading models.
During compilation, the MSVCRT assumes the layout of FILE objects. In multi-threaded builds, FILE objects include an extra CRITICAL_SECTION field to provide locking. The MSVCRT maintains a list of these objects in an array _iob. If one part of an application is built with a different threading model it can lead to memory corruption of the _iob array, lost data and application crash.

Applink solves this by moving all file i/o out of OpenSSL and into your application. But this introduces a problem for those developers working in scripting languages, where the application is the interpreter (ex: python). It may not be practical to request users to rebuild the interpreter.

In the case where you are developing c extensions for your scripting language you can instead arrange to include in your extension and from there invoke OPENSSL_SetApplink. This requires that your extension be compiled using the same threading model as the application and as OpenSSL.

这个理由足够了。

第1个问题弄明白了后,发现第2个问题不需要问了。因为假如在libeay32.dll中实现,那么效果将是这样的:
fopen = UP_fopen
UP_fopen(FILE *fp, int mode){
fopen(fp, mode)
}
哈哈,这没有解决任何问题

关键: openssl不知道你的程序使用什么模式编译的,只有你自己知道,因此你要自己来避免模式不匹配造成的内存泄露