DISCLAIMER: Image is generated using ChatGPT.
I remember when I used to work with ActiveState Perl, I always struggled to find a PPM for CPAN modules. I reached the point where I decided to create the missing PPMs myself, but I never managed to create one, not even once.
Fast forward to my previous workplace, a friend of mine, who was a Release Manager, would always prepare Debian packages for updated CPAN modules. It was fascinating to see how it all worked. I have always been a pure developer, never tried anything outside of programming.
That said, now I try anything and everything, and it gives me complete satisfaction.
A few days ago, while working on my CPAN module DBIx::Class::Async, I decided to create Debian package for it, just for fun. After a quick search online, I found step-by-step guide on how to do it.
In this post, I will take you through the process. At the time of experiment, I had v1.0.3 on CPAN, so I started by downloading the tarball.
$ wget https://cpan.metacpan.org/authors/id/M/MA/MANWAR/DBIx-Class-Async-v1.0.3.tar.gz
Next step was to extract the tarball.
$ tar -xzf DBIx-Class-Async-v1.0.3.tar.gz
$ cd DBIx-Class-Async-v1.0.3
Time to generate the Debian infrastructure.
$ dh-make-perl .
Then check the dependencies as below:
$ dpkg-checkbuilddeps
Luckily no missing dependencies found but I noticed the module description was missing in the control file.
So I added the description in debian/control file like below:
Description: Non-blocking, multi-worker asynchronous wrapper for DBIx::Class
DBIx::Class::Async provides a way to execute DBIx::Class database operations
asynchronously. It allows for multi-worker support, helping to prevent blocking
the main event loop when performing database-heavy tasks in an IO::Async
application.
Finally time to build the package.
$ dpkg-buildpackage -us -uc
Then the fun started: I noticed a few unit tests throwing segfaults. This was unexpected as all tests had passed the last time I checked, and I hadn’t changed the code recently. As you know, segfaults are notoriously difficult to debug.
However, when I ran make test in the local checkout repository, all tests passed.
So why was the build process complaining?
Could the Debian build process involve low level C bindings?
I didn’t have a clue, but I knew that due to the async design, there had to be something missing somewhere.
To deal with this, I needed complete isolation from the outside world, something only possible late at night when everyone else was asleep.
So one night, I decided to dig deep into the source design and found a few missing pieces. I wasn’t entirely sure if they were the root cause, but I investigated further.
Without getting too technical, the root cause was an incorrect teardown order in DBIx::Class::Async::disconnect(). During my investigation, I also found a similar issue in DBIx::Class::Async::Schema::disconnect(). I made a slight change to clone() so that it now shares the parent’s worker pool by default; you only create an independent pool when you pass an explicit worker count.
Why? with many clones sharing the same loop, the concurrent teardown of multiple IO::Async::Function instances caused the loop XS destructor to SEGV during global destruction.
It was definitely worth getting that sorted, a happy byproduct of this random exercise in building a Debian package. I am glad, I chose DBIx::Class::Async for this task.
Once we cleared the SEGV issue, there was still one test file, manifest.t complaining about more files than expected. This was anticipated, so I decided to quiet it by modifying the debian/rules file as below:
$ cat > debian/rules << 'EOF'
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_test:
PERL_DL_NONLAZY=1 prove -Iblib/lib -Iblib/arch \
$(shell find t -name '*.t' | grep -v t/manifest.t | sort)
EOF
Finally, try building the package again.
$ dpkg-buildpackage -us -uc
No more issue, everyone is happy and I have a Debian package libdbix-class-async-perl_1.0.3-1_all.deb.
Time to test the newly built Debian package.
$ cp libdbix-class-async-perl_1.0.3-1_all.deb /tmp
$ cd /tmp
$ sudo apt install ./libdbix-class-async-perl_1.0.3-1_all.deb
Installation using the newly build Debian package was successful.
Finally check the installed package.
$ dpkg -s libdbix-class-async-perl
And with that, the job was done, mission accomplished.
By the way, I have released DBIx::Class::Async v1.0.4 to CPAN with the patch included.
I plan to try this with a few more of my CPAN modules next time I find myself with some spare time.
Happy Hacking !!!
