Create a symbol link for python after installing it on OpenBSD

After installing Python on FreeBSD:

# pkg_add python
quirks-2.304 signed on 2017-04-02T15:01:33Z
Ambiguous: choose package for python
a       0: <None>
        1: python-2.7.13p0
        2: python-3.4.5p2
        3: python-3.5.2p2
        4: python-3.6.0p0
Your choice: 4

It won’t create a symbol link by default:

# python
ksh: python: not found

So for using it handily, you can create a symbol link yourself:

# cd /usr/local/bin
# ln -s python3.6 python

Build gRPC on ArchLinux

Today, I followed Build from Source to compile gRPC on ArchLinux:

 $ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
 $ cd grpc
 $ git submodule update --init
 $ make

Current gRPC‘s release version is v1.4.x:

$ curl -L https://grpc.io/release
v1.4.x

The build flow will generate the errors like this:

......
src/core/lib/support/murmur_hash.c: In function ‘gpr_murmur_hash3’:
src/core/lib/support/murmur_hash.c:79:10: error: this statement may fall through [-Werror=implicit-fallthrough=]
       k1 ^= ((uint32_t)tail[2]) << 16;
       ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core/lib/support/murmur_hash.c:80:5: note: here
     case 2:
     ^~~~
src/core/lib/support/murmur_hash.c:81:10: error: this statement may fall through [-Werror=implicit-fallthrough=]
       k1 ^= ((uint32_t)tail[1]) << 8;
       ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/core/lib/support/murmur_hash.c:82:5: note: here
     case 1:
     ^~~~
cc1: all warnings being treated as errors
......

After referring Fix warnings with GCC 7, I finally make the compilation successful. To facilitate others to build gRPC v1.4.x source code on ArchLinux, I create a patch, and hope it can help others.

P.S.
(1) You should fallback to OpenSSL 1.0. Please refer here:

PKG_CONFIG_PATH=/usr/lib/openssl-1.0/pkgconfig make

Otherwise you may encounter following errors:

src/core/tsi/ssl_transport_security.c: In function ‘tsi_create_ssl_client_handshaker_factory’:
src/core/tsi/ssl_transport_security.c:1281:3: error: ‘TLSv1_2_method’ is deprecated [-Werror=deprecated-declarations]
   ssl_context = SSL_CTX_new(TLSv1_2_method());
   ^~~~~~~~~~~
In file included from /usr/include/openssl/ct.h:13:0,
                 from /usr/include/openssl/ssl.h:61,
                 from src/core/tsi/ssl_transport_security.c:45:
/usr/include/openssl/ssl.h:1624:1: note: declared here
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_method(void)) /* TLSv1.2 */
 ^
src/core/tsi/ssl_transport_security.c: In function ‘tsi_create_ssl_server_handshaker_factory_ex’:
src/core/tsi/ssl_transport_security.c:1389:7: error: ‘TLSv1_2_method’ is deprecated [-Werror=deprecated-declarations]
       impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
       ^~~~
In file included from /usr/include/openssl/ct.h:13:0,
                 from /usr/include/openssl/ssl.h:61,
                 from src/core/tsi/ssl_transport_security.c:45:
/usr/include/openssl/ssl.h:1624:1: note: declared here
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_method(void)) /* TLSv1.2 */
 ^
At top level:
src/core/tsi/ssl_transport_security.c:118:22: error: ‘openssl_thread_id_cb’ defined but not used [-Werror=unused-functio ]
 static unsigned long openssl_thread_id_cb(void) {
                      ^~~~~~~~~~~~~~~~~~~~
src/core/tsi/ssl_transport_security.c:110:13: error: ‘openssl_locking_cb’ defined but not used [-Werror=unused-function]
 static void openssl_locking_cb(int mode, int type, const char *file, int line) {
             ^~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

(2) You may need to change installation directory from /usr/local to /usr:

make prefix=/usr install

This lets you process pkg-config path easily.

Customize ksh display for OpenBSD

The default shell for OpenBSD is ksh, and it looks a little monotonous:

1

To make its user-experience more friendly, I need to do some customizations:

(1) Modify the “Prompt String” to display the user name and current directory:

PS1='$USER:$PWD# '

(2) Install colorls package:

# pkg_add colorls

Use it to replace the shipped ls command:

alias ls='colorls -G'

(3) Change LSCOLORS environmental variable to make your favorite color. For example, I don’t want the directory is displayed in default blue, change it to magenta:

LSCOLORS=fxexcxdxbxegedabagacad

For detailed explanation of LSCOLORS, please refer manual of colorls:

# man colorls
......
LSCOLORS        The value of this variable describes what color to use
                     for which attribute when colors are enabled with
                     CLICOLOR.  This string is a concatenation of pairs of the
                     format fb, where f is the foreground color and b is the
                     background color.

                     The color designators are as follows:

                           a     black
                           b     red
......

This is my final modification of .profile:

......
PS1='$USER:$PWD# '
export PS1
LSCOLORS=fxexcxdxbxegedabagacad
export LSCOLORS
alias ls='colorls -G'
......

And this is the final effect:

Capture
References:
Add Color to Your Terminal;
Why doesn’t alias work in AIX (Korn shell, .profile)?;
ksh.kshrc.

 

My first patch to OpenBSD

Several days ago, I come across 2 posts which introduce OpenBSD Hackathon: Historical: My first OpenBSD Hackathon and Michael W. Lucas: Visiting the OpenBSD t2k13 Hackathon. From the reading, I find OpenBSD is a really distinctive and amazing project, especially after browsing its neat code mirror in github, which makes sure my assumption. So I decided to make my hands dirty on it.

Last weekend, I installed OpenBSD on an old machine, and checked out its fresh code from CVS repository. Because I think reading its code can let me get a better understanding about OpenBSD, even Unix philosophy, I decides to take the dmesg as the first experiment. During the reading, the following code gave me a hit unexpectedly:

......
mib[1] = startupmsgs ? KERN_CONSBUFSIZE : KERN_MSGBUFSIZE;
len = sizeof(msgbufsize);
if (sysctl(mib, 2, &msgbufsize, &len, NULL, 0))
    err(1, "sysctl: KERN_MSGBUFSIZE");
......
mib[1] = startupmsgs ? KERN_CONSBUF : KERN_MSGBUF;
len = msgbufsize;
if (sysctl(mib, 2, bufdata, &len, NULL, 0))
    err(1, "sysctl: KERN_MSGBUF");
    ...... 

The err() function always reports KERN_MSGBUFSIZE error even it is actually KERN_CONSBUFSIZE. So it should be a bug, at least should be an enhancement. I followed Preparing a diff and Making your first patch (OpenBSD) to submit my first OpenBSD patch. Guess what? just few hours later, dmesg source file was changed base on my code. Although the final modification is not my code, it is still a great pleasure that I contribute my own effort to help make OpenBSD better!

Use pdb to help understand python program

As I have mentioned in Why do I need a debugger?:

(3) Debugger is a good tool to help you understand code.

So when I come across difficulty to understand vfscount.py code in bcc project, I know it is time to resort to pdb, python‘s debugger, to help me.

The thing which confuses me is here:

counts = b.get_table("counts")
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
    print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value))

From previous code:

BPF_HASH(counts, struct key_t, u64, 256);

It seems the v‘s type is u64, and I can’t figure out why use v.value to fetch its data here.

pdb‘s manual is very succinct and its command is so similar with gdb‘s, so it is no learning curve for me. Just launch a debugging session and set breakpoint at “counts = b.get_table("counts")” line:

# python -m pdb vfscount.py
> /root/Project/bcc/tools/vfscount.py(14)<module>()
-> from __future__ import print_function
(Pdb) b vfscount.py:49

Start the program and press Ctrl-C after seconds; the breakpoint will be hit:

(Pdb) r
Tracing... Ctrl-C to end.
^C
ADDR             FUNC                          COUNT
> /root/Project/bcc/tools/vfscount.py(49)<module>()
-> counts = b.get_table("counts")

Step into get_table method, and single-step every line. Before leaving method, check the type of keytype and leaftype:

-> counts = b.get_table("counts")
(Pdb) s
--Call--
> /usr/lib/python3.6/site-packages/bcc/__init__.py(416)get_table()
-> def get_table(self, name, keytype=None, leaftype=None, reducer=None):
(Pdb) n
> /usr/lib/python3.6/site-packages/bcc/__init__.py(417)get_table()
-> map_id = lib.bpf_table_id(self.module, name.encode("ascii"))
......
(Pdb) p leaf_desc
b'"unsigned long long"'
(Pdb) n
> /usr/lib/python3.6/site-packages/bcc/__init__.py(430)get_table()
-> leaftype = BPF._decode_table_type(json.loads(leaf_desc.decode()))
(Pdb)
> /usr/lib/python3.6/site-packages/bcc/__init__.py(431)get_table()
-> return Table(self, map_id, map_fd, keytype, leaftype, reducer=reducer)
(Pdb) p leaftype
<class 'ctypes.c_ulong'>
(Pdb) p keytype
<class 'bcc.key_t'>

Yeah! The magic is here: leaftype‘s type is not pure u64, but ctypes.c_ulong. According to document:

>>> print(i.value)
42

We should use v.value to get its internal data.

Happy pdbing! Happy python debugging!