1 2.. _migration_010_100: 3 4libuv 0.10 -> 1.0.0 migration guide 5=================================== 6 7Some APIs changed quite a bit throughout the 1.0.0 development process. Here 8is a migration guide for the most significant changes that happened after 0.10 9was released. 10 11 12Loop initialization and closing 13~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 15In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which 16allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`, 17which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated 18and the user is responsible for allocating the memory and then initializing the loop. 19 20libuv 0.10 21 22:: 23 24 uv_loop_t* loop = uv_loop_new(); 25 ... 26 uv_loop_delete(loop); 27 28libuv 1.0 29 30:: 31 32 uv_loop_t* loop = malloc(sizeof *loop); 33 uv_loop_init(loop); 34 ... 35 uv_loop_close(loop); 36 free(loop); 37 38.. note:: 39 Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init` 40 and :c:func:`uv_loop_close`. 41 42 43Error handling 44~~~~~~~~~~~~~~ 45 46Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters 47would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error` 48to fetch the error code, which was a positive number. 49 50In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or 51a negative number in case of error. 52 53libuv 0.10 54 55:: 56 57 ... assume 'server' is a TCP server which is already listening 58 r = uv_listen((uv_stream_t*) server, 511, NULL); 59 if (r == -1) { 60 uv_err_t err = uv_last_error(uv_default_loop()); 61 /* err.code contains UV_EADDRINUSE */ 62 } 63 64libuv 1.0 65 66:: 67 68 ... assume 'server' is a TCP server which is already listening 69 r = uv_listen((uv_stream_t*) server, 511, NULL); 70 if (r < 0) { 71 /* r contains UV_EADDRINUSE */ 72 } 73 74 75Threadpool changes 76~~~~~~~~~~~~~~~~~~ 77 78In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the 79`QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512 80threads per process. 81 82In 1.0, we unified both implementations, so Windows now uses the same implementation Unix 83does. The threadpool size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment 84variable. See :c:ref:`threadpool`. 85 86 87Allocation callback API change 88~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 89 90In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value: 91 92:: 93 94 uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { 95 return uv_buf_init(malloc(size), size); 96 } 97 98In libuv 1.0 a pointer to a buffer is passed to the callback, which the user 99needs to fill: 100 101:: 102 103 void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { 104 buf->base = malloc(size); 105 buf->len = size; 106 } 107 108 109Unification of IPv4 / IPv6 APIs 110~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111 112libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6` 113duality, there is only :c:func:`uv_tcp_bind` now. 114 115IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took 116``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer). 117It can be stack allocated. 118 119libuv 0.10 120 121:: 122 123 struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234); 124 ... 125 uv_tcp_bind(&server, addr) 126 127libuv 1.0 128 129:: 130 131 struct sockaddr_in addr; 132 uv_ip4_addr("0.0.0.0", 1234, &addr) 133 ... 134 uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); 135 136The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`) 137have also changed, make sure you check the documentation. 138 139..note:: 140 This change applies to all functions that made a distinction between IPv4 and IPv6 141 addresses. 142 143 144Streams / UDP data receive callback API change 145~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 146 147The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer, 148not a structure by value. 149 150libuv 0.10 151 152:: 153 154 void on_read(uv_stream_t* handle, 155 ssize_t nread, 156 uv_buf_t buf) { 157 ... 158 } 159 160 void recv_cb(uv_udp_t* handle, 161 ssize_t nread, 162 uv_buf_t buf, 163 struct sockaddr* addr, 164 unsigned flags) { 165 ... 166 } 167 168libuv 1.0 169 170:: 171 172 void on_read(uv_stream_t* handle, 173 ssize_t nread, 174 const uv_buf_t* buf) { 175 ... 176 } 177 178 void recv_cb(uv_udp_t* handle, 179 ssize_t nread, 180 const uv_buf_t* buf, 181 const struct sockaddr* addr, 182 unsigned flags) { 183 ... 184 } 185 186 187Receiving handles over pipes API change 188~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 189 190In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading 191data on a pipe, which could also result in the reception of handles over it. The callback 192for such function looked like this: 193 194:: 195 196 void on_read(uv_pipe_t* pipe, 197 ssize_t nread, 198 uv_buf_t buf, 199 uv_handle_type pending) { 200 ... 201 } 202 203In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are pending 204handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in 205the read callback: 206 207:: 208 209 void on_read(uv_stream_t* handle, 210 ssize_t nread, 211 const uv_buf_t* buf) { 212 ... 213 while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) { 214 pending = uv_pipe_pending_type((uv_pipe_t*) handle); 215 ... 216 } 217 ... 218 } 219 220 221Extracting the file descriptor out of a handle 222~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 223 224While it wasn't supported by the API, users often accessed the libuv internals in 225order to get access to the file descriptor of a TCP handle, for example. 226 227:: 228 229 fd = handle->io_watcher.fd; 230 231This is now properly exposed through the :c:func:`uv_fileno` function. 232 233 234uv_fs_readdir rename and API change 235~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 236 237`uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in 238libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's 239actually implemented using ``scandir(3)``. 240 241In addition, instead of allocating a full list strings, the user is able to get one 242result at a time by using the :c:func:`uv_fs_scandir_next` function. This function 243does not need to make a roundtrip to the threadpool, because libuv will keep the 244list of *dents* returned by ``scandir(3)`` around. 245